Medium CVSS 5.4 webkit Bypass 🔧 Commit mapped

Overview

Medium
Severity
5.4
CVSS
No
Exploited ITW
Fixed
Fix Status
DescriptionProcessing maliciously crafted web content may prevent Content Security Policy from being enforced
ComponentWebCore Loader
Bug ClassBypass
Tracker278765
Fix commit03fe2d2f0fa8 (WebKit/WebKit)
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N
CISA KEVNot listed
CreditedNarendra Bhati, Manager of Cyber Security at Suma Soft Pvt. Ltd, Pune (India)
Disclosed2024-10-28

Background

Content Security Policy (CSP)
A per-document policy that restricts which origins the page may load or connect to, enforced by the browser to limit injection and exfiltration.
connect-src directive
The CSP directive controlling script-initiated connections such as fetch, XHR, WebSocket, EventSource, and beacon/ping requests.
Hyperlink auditing ping
The ping attribute on <a> elements causes the browser to send a POST notification to the listed URL(s) when the link is followed.
PingLoader::sendPing
The WebCore routine that constructs and dispatches ping/auditing POST requests on behalf of a frame’s document.
allowConnectToSource
The ContentSecurityPolicy method that returns whether a given URL is permitted by connect-src, emitting a refusal console message when it is not.

Root Cause Analysis

The patch modifies PingLoader::sendPing() in Source/WebCore/loader/PingLoader.cpp, the code path that issues hyperlink auditing pings (the ping attribute on anchors, and related beacon-style POSTs).

Before the fix, sendPing() obtained the document and immediately called upgradeInsecureRequestIfNeeded() and built the POST request without ever consulting the document’s Content Security Policy about whether the ping destination was an allowed connection target.

The fix inserts, right after Ref document = *frame.document(), a guard: if (!document->checkedContentSecurityPolicy()->allowConnectToSource(pingURL)) return;. The violated invariant is that network requests initiated on behalf of a document must be vetted against that document’s CSP, and specifically that ping/auditing requests fall under the connect-src directive (the same directive governing fetch/XHR/WebSocket/beacon connections). Because sendPing() skipped allowConnectToSource(), a page could send a ping to a host that its own connect-src policy forbade, so CSP was not enforced for this request type. The added layout tests confirm the semantics precisely: connect-src-ping-allowed.html declares connect-src including localhost:8443 and expects the ping to proceed, while connect-src-ping-blocked.html omits localhost:8443 and expects the console message ‘Refused to connect to https://localhost:8443/ because it does not appear in the connect-src directive of the Content Security Policy.’

The fix restores the invariant by consulting CSP and returning early (silently dropping the ping) when the destination is not permitted, matching how other connect-src-governed loads are gated.

Key insight
A request type (hyperlink auditing pings) was omitted from CSP connect-src enforcement, so the fix is simply to gate sendPing() through allowConnectToSource; the root cause is an incomplete enumeration of CSP-checked connection sinks rather than any flaw in CSP itself.

Attack Path

  1. Author a page under a restrictive CSP The attacker (or attacker-controlled content on a site) operates in a document whose Content-Security-Policy sets a connect-src that is intended to prevent connections to certain hosts.
  2. Emit a ping to a forbidden host Place an anchor with a ping attribute (or otherwise trigger sendPing) targeting a URL not permitted by connect-src, e.g. <a href=… ping=‘https://forbidden-host’>.
  3. Trigger the navigation/click Cause the ping to fire (user click or scripted click()), reaching PingLoader::sendPing().
  4. Bypass the policy Because sendPing() did not call allowConnectToSource, the POST ping is sent to the forbidden host despite connect-src, exfiltrating a beacon/notification the policy was meant to block.
  5. Abuse the covert channel Use the un-vetted ping as a data exfiltration or tracking channel that CSP was supposed to close; this is a policy-enforcement bypass, not memory corruption.

Impact Assessment

This is a security-policy enforcement bypass, not a memory-safety issue: the primitive is the ability to send a ping POST to a host that the page’s connect-src should have blocked, usable for tracking or small-scale exfiltration/beaconing and to defeat a CSP-based containment expectation. There is no memory corruption, no OOB/UAF, and no direct path to code execution; the impact is confined to weakening a policy control within the WebContent process’s networking on behalf of the document. Severity is medium precisely because it undermines a defense-in-depth control rather than granting new memory capabilities.

Changed Functions

FunctionChangeNotes
PingLoader::sendPing
Source/WebCore/loader/PingLoader.cpp
modified Adds an early-return CSP check calling checkedContentSecurityPolicy()->allowConnectToSource(pingURL) so ping requests are gated by connect-src like other connections; previously the check was absent.
connect-src-ping-allowed test
LayoutTests/http/tests/security/contentSecurityPolicy/connect-src-ping-allowed.html
added Verifies a ping to a host present in connect-src is permitted.
connect-src-ping-blocked test
LayoutTests/http/tests/security/contentSecurityPolicy/connect-src-ping-blocked.html
added Verifies a ping to a host absent from connect-src is refused with a CSP console message.
sample resource / expected results
LayoutTests/http/tests/security/contentSecurityPolicy/resources/sample.html (+ *-expected.txt)
added Supporting navigation target and expected-output baselines for the allowed/blocked tests.

Audit Directions

  • Audit PingLoader's other senders
    In PingLoader.cpp check sendViolationReport, sendBeacon-related paths, and any other request-emitting function for a matching allowConnectToSource / CSP check; grep sendPing, sendViolationReport, allowConnectToSource in that file.
  • Enumerate all connect-src sinks
    Grep across Source/WebCore for network requests that should be connect-src-governed (fetch, XHR, WebSocket, EventSource, beacon, ping, report-uri/report-to) and confirm each calls allowConnectToSource before dispatch.
  • Find loaders that skip CSP entirely
    Search loader code for request construction that calls upgradeInsecureRequestIfNeeded or ResourceLoadNotifier without a preceding CSP allow* call, a tell that a request sink was added without policy gating.
  • Check other CSP directives for missing sinks
    Apply the same audit to img-src, media-src, frame-src, and form-action by grepping the corresponding allow* methods (allowImageFromSource, allowFormAction, etc.) against the code paths that actually initiate those loads.

Original Bug Report

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