Securing PAC Scripts in Chromium's Isolated V8 Process
This article provides an overview of how the Chromium web browser securely executes Proxy Auto-Configuration (PAC) scripts. Because PAC scripts are written in JavaScript and are frequently retrieved from untrusted networks using protocols like WPAD, running them directly within core browser components poses severe security risks. To prevent remote code execution and data leaks, Chromium isolates the V8 JavaScript engine inside a dedicated, heavily sandboxed utility process, using secure Inter-Process Communication (IPC) to resolve network proxies safely without exposing the operating system or sensitive user data.
The Security Threat of PAC Scripts
A PAC script defines a JavaScript function called
FindProxyForURL(url, host), which the browser calls before
fetching a web resource to determine where to route the traffic.
Historically, browsers evaluated these scripts inside the main browser
process or the privileged network process.
This created a critical vulnerability: V8 is a complex JavaScript engine, and if an attacker on a local network served a malicious PAC script exploiting a V8 vulnerability, they could immediately gain high-level privileges on the host machine. Furthermore, passing full URLs to a compromised process could leak sensitive path and query data across the network.
The Out-of-Process Architecture
To eliminate this attack vector, Chromium moves PAC execution out of the privileged Network Service and into a dedicated "Proxy Resolver" utility process.
When Chromium detects that a PAC script is required, the browser process launches a new utility process specifically for this task. This process is locked down using the operating system's native sandboxing primitives (such as AppContainer on Windows, Seatbelt on macOS, or seccomp-bpf on Linux). The sandbox strips the process of its ability to read or write to the filesystem, access the clipboard, interact with user interface elements, or make direct network connections.
Stripped-Down JavaScript Environment
Unlike standard renderer processes that run full web pages, the PAC utility process does not load the Blink rendering engine. It initializes a barebones instance of the V8 JavaScript engine.
Because there is no Document Object Model (DOM) or Web APIs, the attack surface is drastically reduced. The V8 context is populated strictly with standard JavaScript built-ins and the few global helper functions required by the PAC specification, such as:
isPlainHostName()dnsDomainIs()myIpAddress()dnsResolve()isInNet()
Communication and DNS Resolution via Mojo
Because the V8 utility process is completely sandboxed from the
network, it cannot download the PAC script itself, nor can it execute
network-dependent PAC functions like dnsResolve() or
myIpAddress(). Chromium solves this using Mojo, its
cross-platform IPC system.
- Script Initialization: The privileged Network Service downloads the PAC script over the network and passes the raw JavaScript code as a string to the V8 utility process over a Mojo pipe.
- Evaluating URLs: When the Network Service needs to
route a request, it sends the
urlandhostover Mojo to the utility process. To protect privacy on HTTPS connections, Chromium frequently strips the path and query components from the URL before sending it to the PAC script, passing only the scheme and host. - Bridging Network Calls: PAC scripts expect
dnsResolve(host)to be synchronous, meaning the JavaScript execution must pause until the IP address is returned. However, the sandbox blocks the utility process from making DNS queries. When the V8 engine hits adnsResolve()call, the utility process pauses the V8 execution thread, sends an asynchronous Mojo request back to the Network Service to perform the DNS lookup, waits for the Mojo response, and then resumes the V8 execution with the resolved IP address. - Returning the Result: Once
FindProxyForURLfinishes executing, the utility process sends the resulting proxy string (e.g.,"PROXY 192.168.1.1:8080; DIRECT") back to the Network Service via Mojo.
Fault Tolerance and Hang Protection
Isolating PAC scripts in a utility process also protects the
browser's stability. Poorly written or malicious PAC scripts can easily
get stuck in infinite while(true) loops or consume
excessive memory.
If a PAC script hangs or crashes due to an out-of-memory error, the main browser and the Network Service remain unaffected. The Network Service monitors the Mojo pipe for timeouts; if the V8 utility process fails to respond within a set timeframe, the browser forcefully terminates the unresponsive utility process, falls back to direct network connections if configured to do so, and spawns a fresh utility process when needed.