CVE-2026-20691
Overview
Background
- Sandbox extension
- A capability token the WebProcess mints and passes to the NetworkProcess to temporarily grant that sandboxed process read (or write) access to a specific local file path.
- NetworkResourceLoadParameters
- The bundle of parameters (request, identifiers, sandbox-extension handles, etc.) sent from the WebProcess to the NetworkProcess to describe a resource load.
- blockedError
- A ResourceError indicating the load was blocked by policy; used here to fail the load cleanly and uniformly when a required sandbox extension cannot be granted.
- Fingerprinting side channel
- Deriving stable distinguishing information about a user’s environment (here, local filesystem state) from observable differences in how requests behave rather than from any explicit data return.
Root Cause Analysis
When the WebProcess schedules a resource load on the NetworkProcess, WebLoaderStrategy::scheduleLoadFromNetworkProcess() builds a NetworkResourceLoadParameters and calls createSandboxExtensionHandlesIfNecessary() to mint sandbox-extension handles that grant the NetworkProcess read access to any local file the load requires (files referenced in an httpBody upload, and, per the shown hunk, the file-system path of the request URL via SandboxExtension::createHandle(request.url().fileSystemPath(), ReadOnly)). Before the patch this function returned void: it attempted to create the handles and then the caller proceeded with the load unconditionally, whether or not handle creation actually succeeded. Sandbox-extension creation for a path can succeed or fail depending on whether that path exists and is accessible, so a load that proceeded without a needed extension would behave observably differently (e.g. proceed to a file read that succeeds or fails, or produce different errors/timing) than one where the extension was granted. That observable difference is a side channel: it lets attacker-controlled web content distinguish states of the local filesystem, which the CVE describes as a fingerprinting capability.
The fix changes createSandboxExtensionHandlesIfNecessary() to return bool — it returns resourceSandboxExtension.has_value() after the httpBody/file-path branch and true when there is no body — so the caller can tell whether a required extension was successfully created. WebLoaderStrategy now checks that return value and, if it is false, dispatches resourceLoader->didFail(blockedError(request)) on the main run loop and returns early, aborting the load uniformly instead of proceeding without the extension. This restores the invariant that a load requiring a local-file sandbox extension either runs with that extension or fails as blocked — never runs in a degraded, path-existence-dependent way — so the success/failure of the load no longer leaks whether the underlying file path was accessible. Note: the middle of the function (the httpBody element loop, diff lines 34-56) is not shown, so the exact set of paths for which handles are created is partly inferred from the visible request.url().fileSystemPath() branch and the function’s name.
Attack Path
- Craft a load referencing a local path From attacker-controlled web content, initiate a resource load whose parameters cause the NetworkProcess to need a sandbox extension for a local file — e.g. a request whose URL resolves to a file-system path, or a form/httpBody element referencing a file — so createSandboxExtensionHandlesIfNecessary() runs against that path.
- Vary the target path Point the load at different candidate local paths whose existence/accessibility the attacker wants to probe.
- Observe pre-patch differential Before the fix, if the extension could not be created the load still proceeded, producing a different observable outcome (success vs a different failure/error/timing) than when the extension was granted; the page reads this back through load success, error type, or timing.
- Infer filesystem state Correlate the observable outcomes across probes to distinguish which paths exist/are accessible, yielding a fingerprint of the local environment (installed apps, user paths, configuration).
Impact Assessment
Changed Functions
| Function | Change | Notes |
|---|---|---|
NetworkResourceLoadParameters::createSandboxExtensionHandlesIfNecessarySource/WebKit/NetworkProcess/NetworkResourceLoadParameters.cpp |
modified | Return type changed from void to bool; now returns resourceSandboxExtension.has_value() for the body/file-path branch and true when there is no httpBody, signaling whether a required sandbox-extension handle was actually created. |
NetworkResourceLoadParameters::createSandboxExtensionHandlesIfNecessary (declaration)Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.h |
modified | Declaration updated from void to bool return to match the definition. |
WebLoaderStrategy::scheduleLoadFromNetworkProcessSource/WebKit/WebProcess/Network/WebLoaderStrategy.cpp |
modified | Now checks the bool result; if handle creation failed it dispatches resourceLoader->didFail(blockedError(request)) on the main run loop and returns early, aborting the load uniformly instead of proceeding without the extension. |
Files Changed
Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.cppSource/WebKit/NetworkProcess/NetworkResourceLoadParameters.hSource/WebKit/WebProcess/Network/WebLoaderStrategy.cpp
Audit Directions
- Other void sandbox-extension helpersGrep for createSandboxExtensionHandle / createSandboxExtensionHandlesIfNecessary and similar SandboxExtension::createHandle callers that ignore the returned std::optional<Handle>, and verify each caller aborts or degrades safely rather than proceeding when the handle is absent.
- Loads that proceed after a failed capability grantAudit WebLoaderStrategy and NetworkProcess load-scheduling paths for places where a capability/extension setup step’s failure does not translate into a uniform didFail(blockedError(…)), which would reintroduce a behavioral differential.
- Path-existence-dependent behavior as an oracleLook across WebKit for request handling that branches on request.url().fileSystemPath() existence/accessibility (file:// handling, form uploads, blob/file body elements) and check whether success/failure/timing differences are observable to web content.