Medium CVSS 7.5 webkit Logic Error 🔧 Commit mapped

Overview

Medium
Severity
7.5
CVSS
No
Exploited ITW
Fixed
Fix Status
DescriptionA remote attacker may be able to view leaked DNS queries with Private Relay turned on
ComponentWebCore PAL
Bug ClassLogic Error
Tracker295943
Fix commit5247bc4ad4b9 (WebKit/WebKit) +9/-1
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
CISA KEVNot listed
CreditedMike Cardwell of grepular.com, Bob Lord
Disclosed2025-09-15

Background

iCloud Private Relay
Apple privacy feature that routes a user’s web traffic (and is expected to route DNS) through two relays so the local network and ISP cannot see the destinations being contacted.
nw_resolver
A CFNetwork/Network.framework object that performs hostname resolution according to given parameters; it can be created from an endpoint or from an already-evaluated network path.
nw_path_evaluator / nw_path
Network.framework machinery that evaluates how traffic to an endpoint should egress (interface, proxy, relay), producing an nw_path that encodes that routing decision.
DNS prefetch
A browser optimization (e.g. rel=dns-prefetch) that resolves hostnames ahead of use, meaning hostnames can be looked up automatically from page content.
privacy_level_silent
An nw_context privacy setting used here to suppress metadata/logging on the resolution, orthogonal to whether the query is actually routed through Private Relay.

Root Cause Analysis

DNSResolveQueueCFNet::performDNSLookup (Source/WebCore/platform/network/cf/DNSResolveQueueCFNet.cpp) performs WebCore’s asynchronous DNS prefetch/resolution using CFNetwork’s low-level nw_resolver API. Before the patch it configured the resolver’s parameters and privacy context (nw_context_set_privacy_level(…, nw_context_privacy_level_silent) and nw_parameters_set_context) and then created the resolver directly from the target endpoint via nw_resolver_create_with_endpoint(hostEndpoint, parameters). The invariant that must hold when iCloud Private Relay is enabled is that name resolution — like the connection itself — must be carried over the Private Relay proxy path rather than being sent as a plaintext query to the locally configured/default DNS servers. Creating a resolver directly from an endpoint apparently does not run the network path evaluation that decides how (and through which proxy/interface) traffic should egress, so the DNS query could be issued outside the Private Relay tunnel, exposing the hostnames being resolved to the local network / ISP even though Private Relay was on.

The fix inserts an explicit path-evaluation step: it creates an nw_path_evaluator for the endpoint with the same parameters (nw_path_create_evaluator_for_endpoint), copies the resulting nw_path (nw_path_evaluator_copy_path), and then builds the resolver from that path (nw_resolver_create_with_path(path)). Resolving over the evaluated path makes the query honor the Private Relay routing/proxy decision, restoring the invariant that DNS is tunneled with the rest of the connection. The companion change in Source/WebCore/PAL/pal/spi/cf/CFNetworkSPI.h merely declares the newly used SPI (the nw_path_evaluator object type and the three functions), which is a prerequisite for calling them and not itself a bug. That the pre-patch path leaked queries is grounded in the CVE description and the direction of the fix; the precise internal reason nw_resolver_create_with_endpoint skips proxy routing is an inference about CFNetwork behavior, not something the diff itself spells out.

Key insight
Creating the DNS resolver directly from the endpoint skipped Network.framework’s path evaluation, so queries egressed outside the Private Relay tunnel; routing resolution through an evaluated nw_path forces DNS to follow the same proxy decision as the connection, which is the actual carrier of the privacy guarantee.

Attack Path

  1. Victim relies on Private Relay for privacy A user browses with iCloud Private Relay enabled, expecting DNS as well as connection traffic to be hidden from the local network and ISP.
  2. Page triggers DNS resolution Any navigation or resource with hostnames — including link rel=dns-prefetch or many subresources on an attacker-controlled page — causes WebCore to call DNSResolveQueueCFNet::performDNSLookup for those hosts.
  3. Resolver created directly from endpoint Pre-patch, the resolver is built via nw_resolver_create_with_endpoint without path evaluation, so the query is emitted over the default network path instead of the Private Relay proxy.
  4. On-path observer captures queries A local-network or ISP-level observer (the attacker) sees the plaintext DNS queries, learning which hostnames the victim is visiting despite Private Relay being on.
  5. Deanonymization / tracking The leaked query stream lets the observer profile the victim’s browsing, defeating the privacy guarantee; there is no memory corruption and no code execution involved.

Impact Assessment

This is an information-disclosure/privacy bug, not a memory-safety issue: the leaked primitive is the set of hostnames the victim resolves, visible to a passive on-path observer (local network, Wi-Fi operator, or ISP) even though Private Relay is engaged. It runs in the process that performs WebCore DNS resolution (the networking path, effectively the Network/UI side of resolution rather than a WebContent memory bug) and yields no control-flow influence, no crash, and no path toward RCE. Realistic escalation is limited to deanonymization, browsing-history inference, and targeting/censorship based on the observed queries. Severity is medium because it silently undermines a privacy guarantee users opt into, but exposure is bounded to metadata rather than content or code execution.

Changed Functions

FunctionChangeNotes
DNSResolveQueueCFNet::performDNSLookup
Source/WebCore/platform/network/cf/DNSResolveQueueCFNet.cpp
modified Replaced nw_resolver_create_with_endpoint(endpoint, parameters) with a path-evaluated flow: create nw_path_evaluator for the endpoint, copy its nw_path, then nw_resolver_create_with_path(path), so DNS honors Private Relay routing.
CFNetworkSPI.h SPI declarations
Source/WebCore/PAL/pal/spi/cf/CFNetworkSPI.h
modified Added OS_OBJECT_DECL/typedef for nw_path_evaluator and declared nw_path_create_evaluator_for_endpoint, nw_path_evaluator_copy_path, and nw_resolver_create_with_path so the new resolver-creation path can be called.

Files Changed

  • Source/WebCore/PAL/pal/spi/cf/CFNetworkSPI.h
  • Source/WebCore/platform/network/cf/DNSResolveQueueCFNet.cpp

Audit Directions

  • Other resolver/connection creations in the CFNet DNS path
    Within DNSResolveQueueCFNet.cpp and sibling CFNet networking code, grep for ’nw_resolver_create_with_endpoint’, ’nw_connection_create’, and any endpoint-first object creation that skips ’nw_path_create_evaluator’ — verify each privacy-sensitive lookup goes through an evaluated path when Private Relay/advanced privacy is active.
  • Private Relay routing consistency across platforms
    Compare the CFNet resolver flow with other DNSResolveQueue backends and platform DNS/proxy code; grep for ‘privacy_level’, ‘PrivateRelay’, ‘HAVE(SYSTEM_SUPPORT_FOR_ADVANCED_PRIVACY_PROTECTIONS)’, and ’nw_parameters’ to find places that set a privacy context but never evaluate a proxy path.
  • New SPI usage correctness
    Audit every caller of nw_resolver_create_with_path / nw_path_evaluator_copy_path (grep those symbols) to ensure the evaluated path is non-null and actually reflects the intended endpoint+parameters, so a failed evaluation does not silently fall back to a leaking default resolution.

Original Bug Report

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