Medium CVSS 5.3 webkit Cross Origin 🔧 Commit mapped

Overview

Medium
Severity
5.3
CVSS
No
Exploited ITW
Fixed
Fix Status
DescriptionCookies belonging to one origin may be sent to another origin
ComponentWebKit UIProcess
Bug ClassCross Origin
Tracker279226
Fix commit11494e677291 (WebKit/WebKit)
CWECWE-346 (Origin validation error)
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
CISA KEVNot listed
CreditedWojciech Regula of SecuRing (
Disclosed2024-10-28

Background

Web archive (.webarchive)
A single-file snapshot of a page and its subresources that WebKit can load, with its own baseURL origin.
Ephemeral / non-persistent data store
A website data store with no on-disk persistence, swapped in for web archive loads to isolate their cookies and storage.
URL string vs filesystem path
url.string() is the full serialized URL (scheme, path, query, fragment, encoding); url.fileSystemPath() is the decoded local path only.
Navigation policy decision
The UIProcess step that decides how a navigation proceeds, including which data store backs it.

Root Cause Analysis

WebPageProxy::receivedNavigationActionPolicyDecision decides whether a navigation should be loaded in a swapped-in non-persistent (ephemeral) website data store, which is done for web archives so their content is isolated. The webarchive detection tested webarchiveURL.string().endsWith(".webarchive") — i.e. it matched the suffix against the full URL string, which includes the query and fragment and percent-encoding, not just the file path. A file URL for a genuine .webarchive that carries a query or fragment (e.g. file:///path/x.webarchive?a or ...x.webarchive#a) has a .string() that does NOT end in .webarchive, so the archive was not recognized and the ephemeral-store swap was skipped; the archive then loaded in the normal persistent data store, so cookies associated with the archive’s origin were read from / written to the shared persistent store and could reach another origin.

The fix matches against webarchiveURL.fileSystemPath(), the decoded filesystem path with query/fragment stripped, so the .webarchive classification reflects the real file rather than an attacker-manipulable URL string, and the ephemeral-store isolation is applied to exactly the webarchive loads it is meant for.

The restored invariant is that ‘is this a .webarchive load’ is decided from the file path, not from a URL string that can be altered without changing the file. This runs in the UIProcess navigation policy path, not the sandboxed WebContent.

Key insight
Classifying a web-archive load by the raw URL string (which includes query/fragment/encoding) instead of the filesystem path let an attacker hide or fake the .webarchive suffix, bypassing the ephemeral-store isolation and leaking cookies across origins.

Attack Path

  1. Host a web archive Get the victim to open a .webarchive file (local file load or substitute data) that should be isolated in an ephemeral data store.
  2. Perturb the URL string Reference the archive with a URL whose string does not end in ‘.webarchive’ though the file path does — e.g. append a query or fragment (x.webarchive?a / x.webarchive#a).
  3. Defeat archive detection endsWith on url.string() fails to match, so receivedNavigationActionPolicyDecision does not swap in the non-persistent store.
  4. Leak cookies across origins The archive loads in the persistent store, so cookies tied to the archive’s baseURL origin are read/written in the shared store and can be sent to another origin.

Impact Assessment

No memory-safety primitive; this is a privacy/isolation logic bug. Mis-detecting web archives caused the ephemeral-store isolation to be skipped, so cookies belonging to one origin could be sent to another origin. It affects data confidentiality/integrity of cookies and executes in the UIProcess navigation path; there is no path to code execution. Rated medium.

Changed Functions

FunctionChangeNotes
WebPageProxy::receivedNavigationActionPolicyDecision
Source/WebKit/UIProcess/WebPageProxy.cpp
modified Detects a web archive with webarchiveURL.fileSystemPath().endsWith(".webarchive") instead of webarchiveURL.string().endsWith(...), so query/fragment/encoding can't hide or fake the archive suffix and ephemeral-store isolation is applied correctly.

Audit Directions

  • Other suffix/extension checks on url.string()
    grep WebKit/WebCore for .string().endsWith( / .startsWith( / contains( on URLs used for security decisions; prefer fileSystemPath()/path() where a file is meant.
  • Data-store / storage-partition selection
    Audit other branches choosing persistent vs ephemeral stores or storage partitions based on URL shape rather than resolved origin.
  • webarchive handling
    Review all isWebArchiveMIMEType / .webarchive handling for consistent path-based classification across load, save, and policy paths.

Original Bug Report

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