CVE-2025-30425
Overview
Background
- ClearKey / EME
- The Encrypted Media Extensions ClearKey CDM; each media key session receives an identifier exposed to script as session.sessionId.
- Process-global static counter
- A single static incremented across all instances/origins, producing a value that persists across contexts.
- Private-browsing isolation
- Contexts that should not share correlatable state; a global counter defeats that isolation.
Root Cause Analysis
This fixes a private-browsing tracking vector: ClearKey EME session identifiers were drawn from a process-global static counter, exposing a persistent, cross-instance value to script. CDMInstanceSessionClearKey::requestLicense assigned each Encrypted Media session an ID from static uint32_t s_sessionIdValue, incremented on every license request across ALL CDM instances and origins. The resulting session.sessionId (readable by the page) is therefore a monotonic, process-wide value that persists across MediaKeys instances and browsing contexts, letting a site correlate or fingerprint a user — including across isolation boundaries such as private browsing — by observing the counter.
The fix scopes the counter to the parent CDM instance: CDMInstanceClearKey gains a per-instance member m_nextSessionIdValue and getNextSessionIdValue(), and requestLicense uses protectedParentInstance()->getNextSessionIdValue() (or an empty string if there is no parent), so session IDs restart per instance and no longer leak a global sequence.
The restored invariant is that session identifiers are scoped to their CDM instance rather than a global counter. The regression test creates two MediaKeys instances and checks each yields session IDs 0 and 1 (not a continuing global sequence).
Attack Path
- Create EME sessions Use ClearKey EME (requestMediaKeySystemAccess org.w3.clearkey) and create media key sessions.
- Read session.sessionId Observe the session ID, which pre-patch came from a global static counter.
- Correlate across contexts Because the counter is process-global and monotonic, its value persists across MediaKeys instances and browsing contexts.
- Track the user Use the persistent, increasing ID to correlate visits / fingerprint the user, including in private browsing.
Impact Assessment
Changed Functions
| Function | Change | Notes |
|---|---|---|
CDMInstanceSessionClearKey::requestLicenseSource/WebCore/platform/encryptedmedia/clearkey/CDMClearKey.cpp |
modified | Derives the session ID from the parent instance's per-instance counter (getNextSessionIdValue) instead of a process-global static, using an empty string when there is no parent. |
CDMInstanceClearKey::getNextSessionIdValue / m_nextSessionIdValueSource/WebCore/platform/encryptedmedia/clearkey/CDMClearKey.h |
modified | Adds a per-instance session-ID counter so IDs are scoped to the CDM instance. |
Files Changed
LayoutTests/http/tests/media/clearkey/clear-key-session-id-expected.txtLayoutTests/http/tests/media/clearkey/clear-key-session-id.htmlSource/WebCore/platform/encryptedmedia/clearkey/CDMClearKey.cppSource/WebCore/platform/encryptedmedia/clearkey/CDMClearKey.h
Audit Directions
- Global counters exposed to scriptGrep the EME/CDM code (and other platform modules) for static counters/IDs whose values are exposed to web content and can persist across instances/origins.
- Session/identifier scopingAudit identifier generation (session IDs, request IDs) to confirm they are scoped to an instance/origin rather than process-global.