[1] NetworkProcess origin-allowlist IPC gating
Rated High because the diff confirms three IPC messages on NetworkConnectionToWebProcess were always dispatchable from any WebContent process and mutated the process-global origin access allowlist consulted by CORS/SOP; the included regression test demonstrates that a compromised renderer turns a same-origin XHR check into a cross-origin data read, which is a direct universal-CORS-bypass primitive on the Network process trust boundary.
Origin access allowlist IPC messages on NetworkConnectionToWebProcess modify a process-global allowlist with no validation, allowing a compromised WebContent process to bypass CORS for all connections. These messages are only used by TestRunner SPI. Gate them behind EnabledBy=AllowTestOnlyIPC so they are rejected unless the test-only flag is set.
Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in
Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml
Tools/TestWebKitAPI/Tests/WebKit/WKWebView/IPCTestingAPI.mm
Patch Details
The patch tags three IPC messages — AddOriginAccessAllowListEntry, RemoveOriginAccessAllowListEntry, and ResetOriginAccessAllowLists — with [EnabledBy=AllowTestOnlyOriginAccessAllowListIPC] in NetworkConnectionToWebProcess.messages.in. The corresponding preference is introduced in UnifiedWebPreferences.yaml with sharedPreferenceForWebProcess: true and default: false, then wired into WebKitTestRunner (TestOptions.cpp, TestOptions.h, TestController.cpp) so layout tests can opt in. Two regression tests (AddOriginAccessAllowListEntryRequiresTestOnlyIPC and AddOriginAccessAllowListEntryAllowedWithTestOnlyIPC) drive the IPC via the IPC testing API across two WKWebViews sharing a process pool and demonstrate the bypass is reachable when the flag is off and blocked when it is.
Test-only IPC entry point exposed on the production renderer-to-network surface, allowing a compromised WebContent process to mutate process-global same-origin/CORS policy without authorization.
Background
WebKit splits the browser into multiple processes; WebContent runs untrusted web content, and NetworkProcess performs all network I/O on its behalf, communicating via Mach IPC. NetworkConnectionToWebProcess is the per-WebContent endpoint inside NetworkProcess; the messages it accepts are declared in NetworkConnectionToWebProcess.messages.in and dispatched by code generated from that file.
The [EnabledBy=Pref] annotation on a message declaration tells the generator to inject a runtime check against the named preference — when the preference is false, the message is rejected before its handler runs. sharedPreferenceForWebProcess: true causes the preference value to be propagated from the UI process to the WebContent and Network processes so the generated check can see it.
The origin access allowlist (SecurityOrigin::addOriginAccessAllowlistEntry and its OriginAccessPatterns storage) is a process-global table of (source, protocol, host, subdomains) tuples; same-origin and CORS checks consult it, and a matching entry causes a cross-origin access to be treated as same-origin. The TestRunner SPI exposes a function so layout tests can populate this allowlist to simulate cross-origin scenarios — that is the API's only intended consumer.
Analysis
The bug is a missing IPC authorization check. Before the fix, the three origin-allowlist messages on NetworkConnectionToWebProcess were always dispatchable from any WebContent process with no validation. Their handlers mutate the process-global origin allowlist that SecurityOrigin::canAccess and the CORS path consult when deciding whether a cross-origin network access is permitted. The allowlist API exists only to support TestRunner SPI, so its presence on a production IPC surface is a trust-boundary violation: a compromised WebContent process could append an entry of its choosing, and from that point onward any page loaded by any WebContent process sharing that Network process is exempted from CORS for the chosen destination.
The included regression test demonstrates the exact primitive. Page A on 127.0.0.1 injects an allowlist entry whitelisting localhost → 127.0.0.1, then page B on localhost performs xhr.open('GET', 'http://127.0.0.1:.../target'). With the flag off the assertion is BLOCKED:; with the flag on it is FETCHED:cross-origin-data. The same primitive turns post-renderer-compromise into a credentialed cross-origin read against arbitrary HTTP(S) origins: an attacker would send AddOriginAccessAllowListEntry with sourceOrigin=http://attacker.example, destinationProtocol=http, destinationHost=victim.example, allowDestinationSubdomains=true, then fetch victim.example from any attacker page and read the cookie-bearing response body.
The cross-process security model assumes that a compromised WebContent process is still constrained by the Network process to honour CORS for cross-origin reads — the Network process is the policy enforcement point a compromised renderer cannot talk past. This vulnerability weakens exactly that boundary. The allowlist is process-global, so the bypass also affects every other WebContent process sharing the same Network process for the lifetime of the allowlist (or until ResetOriginAccessAllowLists is sent).
The choice to gate behind a new preference (AllowTestOnlyOriginAccessAllowListIPC) rather than the existing umbrella AllowTestOnlyIPC is deliberate: tests that need the allowlist API can be enabled in isolation without flipping the broader test-only IPC switch, which keeps the additional risk surface minimised for the rest of the test suite.
Audit directions
- IPC messages introduced to serve
TestRunnerSPI but never gated with anEnabledBy=AllowTestOnly*IPCannotation. Audit every*.messages.infile inSource/WebKit/for messages whose only production caller isWebKitTestRunnerorDumpRenderTree, and verify each has a test-only[EnabledBy=...]annotation. Start withNetworkConnectionToWebProcess.messages.in,WebPageProxy.messages.in,GPUConnectionToWebProcess.messages.in, andNetworkProcess.messages.in; grep for messages whose only references inSource/WebKit/UIProcess/API/are under test SPI paths. - IPC handlers that mutate process-global or per-network-session security policy with no per-origin or per-page scoping. Audit
NetworkConnectionToWebProcessandNetworkProcessfor any handler that writes to global state used by CORS / SOP / CSP / CORP / fetch metadata enforcement. The risk is that the cross-process model assumes Network-process state is per-page or per-session, but a global write turns a single-renderer compromise into a global policy weakening. Start by greppingSource/WebKit/NetworkProcess/forstaticors_storage touched from message handlers; cross-check againstWebCore::SecurityOriginallowlist/blocklist APIs. - Gating a sensitive IPC behind a new preference rather than an existing umbrella one. This creates a risk of misconfiguration where a future test or embedder turns the new preference on without realising it implies test-only trust. Verify that
AllowTestOnlyOriginAccessAllowListIPCis never set totrueoutsideWebKitTestRunner/TestWebKitAPI, and that no production embedder API exposes it. GrepSource/WebKit/andTools/for the preference name and any SPI surface that might let an app toggle it. - Symmetric
Remove*andReset*operations on other allowlist/blocklist APIs reachable via ungated IPC. The reset primitive is independently useful to an attacker because it can clear policy hardening (e.g., wipe entries an embedder explicitly added). Audit anyReset*/Clear*message inSource/WebKit/NetworkProcess/*.messages.inthat does not require an authenticated caller.