Medium CVSS 8.1 webkit Cross Origin 🔧 Commit mapped

Overview

Medium
Severity
8.1
CVSS
No
Exploited ITW
Fixed
Fix Status
DescriptionA malicious website may exfiltrate data cross-origin
ComponentWebCore Loader
Bug ClassCross Origin
Tracker276208
Fix commit0473037b5502 (WebKit/WebKit) +107/-0
CWECWE-942
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N
CISA KEVNot listed
CreditedAleksejs Popovs
Disclosed2025-11-03

Background

Opaque source (loadedFromOpaqueSource)
Marks a cross-origin response so its contents and detailed timing are hidden from script, per the same-origin policy.
MediaResourceLoader
Loads media resources for HTMLMediaElement, including HLS playlists and their sub-resources.
CORS mode (m_crossOriginMode)
Whether the media element requested cross-origin access with CORS; null means no CORS, so cross-origin data must stay opaque.
Resource Timing
A performance API that can expose per-resource load timing, which must be coarsened/withheld for opaque cross-origin resources.

Root Cause Analysis

MediaResourceLoader loads media resources (e.g. HLS playlists and their segment/sub-resources) for a <video>/<audio> element. Whether a response is treated as an opaque cross-origin resource – which prevents script from observing its data and detailed timing – is controlled by loaderOptions.loadedFromOpaqueSource.

Pre-patch, cross-origin media sub-resources fetched after the main resource were not consistently marked opaque, so a cross-origin media stream loaded without CORS could leak data/timing (for example via Resource Timing entries or otherwise observable response state), i.e. cross-origin information disclosure.

The fix adds tracking of whether the main resource has loaded (m_wasMainResourceLoaded) and, in requestResource, marks a request opaque when it is cross-origin and uncredentialed by CORS: if (!m_document->securityOrigin().isSameOriginAs(SecurityOrigin::create(request.url())) && m_crossOriginMode.isNull() && m_wasMainResourceLoaded) loaderOptions.loadedFromOpaqueSource = Yes; else if (!m_wasMainResourceLoaded) m_wasMainResourceLoaded = true;. In other words, the first (main) resource load flips the flag, and subsequent cross-origin, non-CORS sub-resource loads are forced to opaque so their contents/timing are not exposed.

The restored invariant is that cross-origin media sub-resources without CORS are treated as opaque, closing the cross-origin data/timing leak.

The added tests cover cross-origin media resource-timing with and without CORS.

Key insight
MediaResourceLoader failed to mark cross-origin, non-CORS media sub-resources as loaded-from-opaque-source, leaking their cross-origin data/timing; forcing those loads opaque (once the main resource has loaded) restores the boundary.

Attack Path

  1. Point media at a cross-origin stream Load a <video>/<audio> whose src is a cross-origin HLS playlist (or similar) that references sub-resources, without proper CORS.
  2. Let sub-resources load After the main playlist loads, the media engine fetches cross-origin segments/sub-resources through MediaResourceLoader.
  3. Observe non-opaque responses Pre-patch, those cross-origin sub-resource loads were not marked loadedFromOpaqueSource, so their data/timing were observable (e.g. Resource Timing).
  4. Exfiltrate cross-origin info Read the leaked cross-origin response data/timing – a same-origin-policy / information-disclosure bypass in WebContent.

Impact Assessment

A cross-origin information-disclosure bug: cross-origin, non-CORS media sub-resources were not marked opaque, exposing their data/timing to script. It is a same-origin-policy leak with no memory-safety component, in the WebContent process. Rated medium.

Changed Functions

FunctionChangeNotes
MediaResourceLoader::requestResource
Source/WebCore/loader/MediaResourceLoader.cpp
modified Marks a request loadedFromOpaqueSource when it is cross-origin, CORS mode is null, and the main resource already loaded; the first load sets m_wasMainResourceLoaded.
MediaResourceLoader::m_wasMainResourceLoaded
Source/WebCore/loader/MediaResourceLoader.h
modified New flag distinguishing the initial main resource load from subsequent (sub-)resource loads.

Files Changed

  • LayoutTests/http/tests/media/resources/hls/.htaccess
  • LayoutTests/http/tests/performance/performance-resource-timing-cross-origin-media-expected.txt
  • LayoutTests/http/tests/performance/performance-resource-timing-cross-origin-media-with-cors-expected.txt
  • LayoutTests/http/tests/performance/performance-resource-timing-cross-origin-media-with-cors.html
  • LayoutTests/http/tests/performance/performance-resource-timing-cross-origin-media.html
  • LayoutTests/platform/glib/TestExpectations
  • LayoutTests/platform/win/TestExpectations
  • Source/WebCore/loader/MediaResourceLoader.cpp
  • Source/WebCore/loader/MediaResourceLoader.h

Audit Directions

  • Other loadedFromOpaqueSource gaps
    grep WebCore/loader and media for loadedFromOpaqueSource and confirm every cross-origin non-CORS load path sets it.
  • Media sub-resource origins
    Audit HLS/DASH/playlist sub-resource fetching for consistent same-origin checks against the document origin, not just the manifest origin.
  • Timing exposure
    Review Resource Timing / server-timing exposure for media resources to ensure opaque responses are coarsened.

Original Bug Report

The reporter's bug is still restricted on the tracker.