Medium CVSS 5.3 webkit Logic Error 🔧 Commit mapped

Overview

Medium
Severity
5.3
CVSS
No
Exploited ITW
Fixed
Fix Status
DescriptionPrivate Browsing tabs may be accessed without authentication
ComponentWebCore HTML
Bug ClassLogic Error
Tracker275272
Fix commit7bd7a6672460 (WebKit/WebKit)
CWECWE-287
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
CISA KEVNot listed
CreditedMatthew Butler
Disclosed2024-07-29

Background

Now Playing info
A metadata record (title, artist, album, artwork, playback state) WebKit publishes to the operating system so currently playing media appears in Control Center, the lock screen, and remote-control surfaces.
Ephemeral session
The non-persistent session type used by Private Browsing, where cookies, storage, and other state are kept in memory and are meant to leave no persistent, externally visible trace.
MediaElementSession
The WebCore object that mediates between an HTMLMediaElement and platform media services, computing eligibility and the Now Playing payload for the element.
mediaPlaybackIsSuspended
A per-page flag indicating the page’s media playback is currently suspended, during which media metadata should not be advertised to the system.

Root Cause Analysis

The bug is an information-disclosure logic error in WebKit’s Now Playing integration. When a media element or Web Audio context plays audio, WebCore computes a NowPlayingInfo structure (title, artist, album, artwork, unique identifier) and hands it to the platform so the media can be surfaced in system UI such as Control Center, the lock screen, and the Now Playing widget.

The invariant that was violated is that content playing inside a private-browsing (ephemeral) session must never leak identifying metadata to persistent, system-visible surfaces, and that metadata must not be published while media playback for the page is suspended. Before the patch, HTMLMediaElement::isNowPlayingEligible() unconditionally returned m_mediaSession->hasNowPlayingInfo() and MediaElementSession::computeNowPlayingInfo() / AudioContext::nowPlayingInfo() built and returned the full info record without consulting the page’s session type, so a private tab’s media title (which can reveal the visited site or content) was exposed through the system Now Playing interface.

The fix adds explicit ephemeral-session and suspension gates: AudioContext::isNowPlayingEligible() now returns false when there is no document or when page->mediaPlaybackIsSuspended(); AudioContext::nowPlayingInfo() returns an empty/placeholder record early when page->usesEphemeralSession(); HTMLMediaElement gains an out-of-line isNowPlayingEligible() that also returns false when playback is suspended; and MediaElementSession::computeNowPlayingInfo() null-checks the page and, for an ephemeral session, blanks title/artist/album/artwork before returning. These changes restore the invariant that ephemeral browsing produces no persistent, cross-context-visible Now Playing metadata. This is purely a policy/logic fix; nothing in the diff touches memory management, so there is no memory-corruption primitive here — the harm is confined to leaking private-session information to the local system UI.

Key insight
The root cause is a missing session-type policy check on a data path that crosses from a private (ephemeral) browsing context into persistent, system-visible UI; the fix is to gate Now Playing eligibility and metadata population on usesEphemeralSession() and mediaPlaybackIsSuspended() so private-session content never populates shared surfaces.

Attack Path

  1. Open media in a private tab A user opens a Private Browsing tab and navigates to a page (attacker-controlled or benign) that plays audio via an <audio>/<video> element or a Web Audio AudioContext.
  2. Metadata is computed WebCore’s media session builds NowPlayingInfo from the element’s mediaSessionTitle() and related fields without checking that the owning page uses an ephemeral session.
  3. Metadata is published to system UI Because isNowPlayingEligible() returns true and computeNowPlayingInfo()/nowPlayingInfo() return the populated record, the private-tab title/artist/artwork are pushed to Control Center, the lock screen, and the Now Playing widget where they persist and are visible outside the private session.
  4. Observation without authentication Anyone with physical or shoulder-surfing access to the device (including at the lock screen, which requires no unlock) can read the leaked title/URL-derived metadata, effectively revealing private-browsing activity that was supposed to be unauthenticated-inaccessible.

Impact Assessment

This is an information-disclosure/privacy bug, not a memory-safety primitive: the diff contains no allocation, lifetime, or bounds logic that could be turned toward OOB/UAF, and there is no path to memory corruption or code execution from it. The concrete harm is that private-browsing media metadata (a title that can reveal the visited site or content) leaks to persistent, system-level Now Playing surfaces that are readable without authenticating the device (e.g. at the lock screen). It executes in and leaks from the WebContent process’s media pipeline into the platform’s shared Now Playing state; severity is medium precisely because it is a confidentiality leak rather than an exploitation chain.

Changed Functions

FunctionChangeNotes
AudioContext::isNowPlayingEligible
Source/WebCore/Modules/webaudio/AudioContext.cpp
modified Adds a null-document guard and returns false when the page's media playback is suspended, before falling through to hasPlayBackAudioSession().
AudioContext::nowPlayingInfo
Source/WebCore/Modules/webaudio/AudioContext.cpp
modified Returns the placeholder nowPlayingInfo early when page->usesEphemeralSession(), so private-session Web Audio never populates media-session metadata.
HTMLMediaElement::isNowPlayingEligible
Source/WebCore/html/HTMLMediaElement.cpp
added New out-of-line definition (previously an inline one-liner) that returns false when page->mediaPlaybackIsSuspended(), otherwise defers to m_mediaSession->hasNowPlayingInfo().
MediaElementSession::computeNowPlayingInfo
Source/WebCore/html/MediaElementSession.cpp
modified Adds a null-page early return and, for an ephemeral session, blanks title/artist/album/artwork before returning so no identifying metadata escapes a private tab.
HTMLMediaElement::isNowPlayingEligible (declaration)
Source/WebCore/html/HTMLMediaElement.h
modified Changes the inline `{ return m_mediaSession->hasNowPlayingInfo(); }` to an out-of-line declaration so the suspension check can be added.

Audit Directions

  • Other Now Playing / media-session outputs
    Audit every producer of NowPlayingInfo and every isNowPlayingEligible()/computeNowPlayingInfo()/nowPlayingInfo() override (grep for NowPlayingInfo, hasNowPlayingInfo, updateNowPlayingInfo) to confirm each consults usesEphemeralSession() before emitting title/artist/artwork.
  • Ephemeral-session leaks in other platform bridges
    Grep for usesEphemeralSession() and, conversely, for places that push page-derived strings to the OS (media remote, MediaSession API, spotlight/handoff, notifications) that do NOT check it — those are candidate private-mode leaks with the same shape.
  • Suspended-playback gaps
    Grep for mediaPlaybackIsSuspended and confirm all metadata/remote-control code paths honor it; look for sibling PlatformMediaSession subclasses whose eligibility still ignores suspension.

Original Bug Report

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