Responding to an ITW Chrome Sandbox Escape (Twice!)
Alex Gough (Platform Security and Security Review, Chrome · Google)
Kawaiicon 2025 (Kawaiicon III) · Day 2 · Main Stage
Overview
In this compelling talk from Kawaiicon, Alex Gough of Google's Chrome security team provides a detailed, post-mortem analysis of two critical in-the-wild (ITW) sandbox escape vulnerabilities discovered in Chrome within weeks of each other. Gough takes the audience on a journey through the intricate debugging process, the technical specifics of the exploits, and the profound architectural changes implemented in response. The talk highlights the relentless cat-and-mouse game between attackers and defenders in the highly privileged environment of a web browser.

Key moments
- 0:00 Introduction to Chrome's sandboxing security model
- 2:00 Understanding Windows handles and DuplicateHandle
- 4:30 First sandbox escape reported by Kaspersky
- 8:00 Root cause: DuplicateHandle and pseudo handles
- 10:30 Fixing the bug and postmortem lessons learned
- 14:50 Second sandbox escape: IPC trust confusion
- 22:00 Key takeaways for robust security response
Responding to an ITW Chrome Sandbox Escape (Twice!)
Speakers: Alex Gough, Platform Security and Security Review, Chrome, Google
Conference: Kawaiicon
YouTube: https://www.youtube.com/watch?v=mxN8puPTLCs
Overview
In this compelling talk from Kawaiicon, Alex Gough of Google's Chrome security team provides a detailed, post-mortem analysis of two critical in-the-wild (ITW) sandbox escape vulnerabilities discovered in Chrome within weeks of each other. Gough takes the audience on a journey through the intricate debugging process, the technical specifics of the exploits, and the profound architectural changes implemented in response. The talk highlights the relentless cat-and-mouse game between attackers and defenders in the highly privileged environment of a web browser.
The presentation focuses on the complexities of securing a modern web browser, where untrusted code from countless websites must be rigorously isolated from the user's system. It underscores the critical role of the sandbox in preventing arbitrary code execution from escalating into full system compromise. Gough's account is particularly valuable for its candid exploration of assumptions, overlooked details, and the iterative nature of security improvements within a massive, complex codebase like Chrome.
This talk is essential for anyone interested in browser security, operating system internals, incident response, and secure software development practices. It provides a rare glimpse into how a leading security team responds to sophisticated, real-world attacks, not just patching immediate vulnerabilities but also performing deep architectural reviews to prevent entire classes of future bugs. The insights shared regarding post-mortems, variant analysis, and the importance of robust internal documentation and external bug bounty programs are universally applicable across the security industry.
Background
▶ Watch: Introduction to Chrome's sandboxing security model (0:00)
Modern web browsers like Chrome operate as highly complex application platforms, executing untrusted code from numerous sources (websites, ads, extensions) on a user's computer. To mitigate the inherent risks, Chrome employs a multi-process architecture where each website runs in its own isolated process, known as a renderer process. These renderer processes are heavily sandboxed, meaning their capabilities are severely restricted by the operating system (OS) to prevent them from accessing local files, other processes, or sensitive system resources. The goal is to ensure that even if an attacker compromises the code running within a website (e.g., through a V8 engine bug), they cannot escape the sandbox and affect the rest of the system.
While renderer processes are highly restricted, other Chrome processes, such as the browser process (the main, privileged process), require broader access to the OS for tasks like drawing the UI, managing files, and handling network requests. This necessitates a secure mechanism for privileged processes to communicate with sandboxed ones and share resources. This is where Windows handles and Interprocess Communication (IPC) become crucial and, as the talk illustrates, potential points of vulnerability.
In Windows, handles are opaque identifiers that represent OS objects (e.g., files, processes, threads, pipes). A process interacts with these objects through its handles, and the kernel tracks what a handle refers to and what operations can be performed with it. Chrome extensively uses the DuplicateHandle Windows API call to transfer handles between processes. A privileged process (like the browser) can open a file, perform checks, and then use DuplicateHandle to "zap" a copy of that handle into a sandboxed renderer process, allowing the renderer to interact with the specific resource without direct OS access.
Chrome's IPC mechanism facilitates communication between these processes. Initially, a simple pipe is established between the browser and each renderer. For more complex interactions, like a renderer sending images to the GPU process, the browser acts as a relay, creating pipes and using DuplicateHandle to establish direct connections. A critical component of Chrome's low-level IPC protocol is the RelayMessage function, which allows a renderer to ask the browser to forward a handle to another process (e.g., GPU). The browser is supposed to validate these requests rigorously, ensuring only safe handles are transferred to appropriate destinations. The talk also introduces IPCZ, a newer, more complex IPC mechanism used for specialized, trusted connections within Chrome, such as those for the updater or notification services. These trusted connections have different security assumptions, which attackers can potentially exploit.
Key Findings
▶ Watch: First sandbox escape reported by Kaspersky (4:30)
The talk details two distinct, in-the-wild (ITW) sandbox escape vulnerabilities found in Chrome, both leveraging flaws in handle management and interprocess communication.
The first vulnerability (CVE-2022-1096) was a critical sandbox escape where a compromised renderer process could obtain a fully privileged handle to a thread within the browser process. This was achieved by exploiting a dangerous interaction between Chrome's IPC deserialization, the Windows DuplicateHandle API, and the concept of pseudo-handles. Attackers crafted an IPC message containing a fake handle value (0xFFFFFFFE), which corresponds to the GetCurrentThread pseudo-handle. The browser, when attempting to duplicate this "handle" from the renderer back to the renderer via a relay, unknowingly short-circuited the DuplicateHandle call due to kernel behavior. This resulted in the browser itself providing a real, highly privileged handle to its own thread to the untrusted renderer, allowing for arbitrary code execution in the browser process.
The second vulnerability (CVE-2022-1369), discovered shortly after the first, was a more sophisticated sandbox escape that bypassed the initial fixes. This bug exploited IPCZ trust confusion and handle guessing. Attackers used the RequestIntroduction IPC message to trick the browser into believing a connection from the renderer was actually a trusted, internal connection (e.g., from a "broker" or itself). By manipulating the trust metadata associated with IPCZ transports, the renderer could send a message containing a guessed, valid handle ID (e.g., a common thread handle ID in the browser process at startup). Because the browser was confused about the source of the message, it bypassed the strict trust checks that would normally prevent sending sensitive handles to untrusted renderers. This allowed the renderer to again receive a privileged handle to a browser thread, albeit with slightly less reliability due to the nature of handle guessing and potential side effects of DuplicateHandle closing the source handle.
Both findings highlight the extreme difficulty in perfectly securing complex IPC mechanisms and the subtle ways operating system APIs can behave unexpectedly, leading to severe security flaws. The rapid discovery of the second bug after the first underscores the importance of not just patching a specific vulnerability but conducting comprehensive post-mortems and variant analysis.
Technical Deep Dive
▶ Watch: Root cause: DuplicateHandle and pseudo handles (8:00)
First Sandbox Escape (CVE-2022-1096): Pseudo-Handle Abuse
The initial bug hinged on a misunderstanding of how Windows' DuplicateHandle function interacts with pseudo-handles. Pseudo-handles are special constant values (e.g., 0xFFFFFFFF for GetCurrentProcess, 0xFFFFFFFE for GetCurrentThread) that refer to the calling process or thread, respectively. They are not real kernel object handles and are only valid in the context of the process using them. Chrome's IPC mechanism allowed a renderer to send a message requesting the browser to "relay" a handle. The renderer would embed the 0xFFFFFFFE value, claiming it was a handle it possessed.
The vulnerability unfolded as follows:
- Renderer sends fake handle: A compromised renderer sends an IPC message, via
RelayMessage, to the browser. This message contains0xFFFFFFFE, pretending to be a handle from the renderer that needs to be duplicated and sent elsewhere (ultimately back to the renderer). - Browser deserializes and attempts duplication: The browser process receives this message. During deserialization, it performs some initial checks, but crucially, it does not fully validate if
0xFFFFFFFEis a legitimate handle within the renderer's context. A previous check for0xFFFFFFFF(theGetCurrentProcesspseudo-handle) existed, preventing that specific value from being used, but0xFFFFFFFEwas overlooked. DuplicateHandleshort-circuit: The browser then callsDuplicateHandle(source_process_handle, 0xFFFFFFFE, destination_process_handle, ...)wheresource_process_handlerefers to the renderer. According to theDuplicateHandledocumentation, the handle being duplicated "must be valid in the context of the source process." However, analysis using tools like Ghidra revealed that the Windows kernel, when presented with a pseudo-handle value like0xFFFFFFFE, performs a short-circuit evaluation. Instead of validating0xFFFFFFFEagainst thesource_process_handle(the renderer), it immediately interprets it asGetCurrentThreadin the context of the calling process (which is the browser).- Browser duplicates its own thread handle: As a result,
DuplicateHandleeffectively duplicates the browser's own current thread handle. This handle is a real kernel object handle, representing the browser thread with full access (0x1FFFFForALL_ACCESS). - Privileged handle sent back to renderer: The browser, unaware of the pseudo-handle trickery, then sends this newly duplicated (and highly privileged) browser thread handle back to the renderer. The renderer now possesses an "all-access party pass" to a thread running within the browser process, enabling a full sandbox escape.
Debugging this required Time Travel Debugging (similar to RR on Linux) to trace handle creation and message passing across process boundaries. Placing breakpoints on DuplicateHandle calls and IPC send/receive functions eventually revealed the unexpected 0xFFFFFFFE value and its transformation into a valid browser thread handle.
Second Sandbox Escape (CVE-2022-1369): IPCZ Trust Confusion
The second bug emerged weeks later, demonstrating a variant that bypassed the initial pseudo-handle fixes. This attack targeted IPCZ, Chrome's advanced IPC mechanism designed for more complex, often trusted, inter-process communication scenarios (e.g., for the updater or notification services). IPCZ maintains trust metadata associated with each transport, indicating whether the connected process is trusted or untrusted.
The attack chain was intricate:
- Renderer requests introduction, lies about identity: A compromised renderer sends an IPCZ
RequestIntroductionmessage. Crucially, it lies about its identity, claiming it wants to talk to a trusted component or even the browser itself acting as a "broker." - Browser establishes "trusted" transport: The browser, believing the renderer's false claim, responds by establishing a new IPCZ transport. The metadata for this transport incorrectly marks the renderer as a trusted entity, believing it's talking to itself or another trusted broker.
- Renderer re-sends transport to browser: The renderer then sends this "trusted" transport handle back to the browser in a completely unrelated message. The browser, seeing this transport (which it believes is from a trusted source, based on the manipulated metadata), interprets it as a connection from itself.
- Bypassing trust checks: Now, when the renderer sends a message containing a handle to be duplicated, the browser's deserialization path (specifically the
TransferHandlefunction) is misled by the corrupted trust metadata. It incorrectly assumes the handle is coming from or going to a trusted process, bypassing the strict checks implemented after CVE-2022-1096 that prevent sending sensitive handles to untrusted renderers. - Handle Guessing: Instead of a pseudo-handle, the renderer now needs a real handle. Attackers found that Windows handle IDs are often allocated sequentially and predictably (e.g., starting at 4, then 8, etc.). By knowing the common handle IDs for critical browser threads (e.g., the main thread handle at startup), the renderer could guess a valid handle ID.
- Duplication and Escape: When
DuplicateHandleis called with this guessed, valid handle ID, it successfully duplicates a real browser thread handle. Because the browser's trust checks are bypassed, this privileged handle is then sent back to the renderer, again leading to a sandbox escape.
This bug was less reliable than the first because DuplicateHandle closes the source handle. If the renderer guessed incorrectly, it could close a critical browser handle, potentially crashing the browser rather than exploiting it. Debugging this was "not easy" due to the "1980s macro mess" of the IPCZ message generation code, which made setting breakpoints and dissecting messages extremely challenging.
Demo / Proof of Concept
▶ Watch: Second sandbox escape: IPC trust confusion (14:50)
While the talk did not feature a live demonstration, Alex Gough explicitly referenced the existence and utility of the exploit code. For the first vulnerability, Kaspersky provided a compiled DLL, which the Chrome team had to analyze in sandbox VMs using debuggers and Sysinternals tools. For the second vulnerability, the bug reporter provided actual source code, including a patch to the Chromium renderer, which was invaluable for understanding and reproducing the exploit. The speaker's team used these proof-of-concept exploits to debug, trace execution paths with Time Travel Debugging, and confirm the precise mechanism of the sandbox escapes. The speaker even mentioned helping the researcher "write the exploit that helped us pay him even more money," indicating a collaborative approach to understanding the PoC.
Defensive Implications
▶ Watch: Key takeaways for robust security response (22:00)
The response to these ITW sandbox escapes led to a series of significant defensive improvements across Chrome's security architecture and development practices.
Fixes for CVE-2022-1096 (Pseudo-Handle Abuse):
- Reject all pseudo-handle values: The most direct fix was to modify IPC deserialization to explicitly reject all known pseudo-handle values (
-1through-6) when receiving handles from untrusted processes. This ensuresDuplicateHandleis never called with such values in an untrusted context. - Handle Type Wrapping: Chrome's internal C++ wrapper types for handles were updated to prevent their creation from pseudo-handle values. Attempting to construct a handle wrapper with a pseudo-handle now results in an explosion, making it "unrepresentable or uncreatable" and forcing developers to use specific, audited "dances" for legitimate (and rare) cases.
- Enhanced
TransferHandleChecks: TheTransferHandlefunction, responsible for sending handles between processes, previously had aDCHECK(developer debug assertion) that would crash during development builds if a thread handle was sent to a renderer. This check was promoted to a production-level check, making it impossible for the browser to send sensitive handle types (like thread handles) to untrusted renderers, except for a very small, explicitly whitelisted set of handle types.
Fixes for CVE-2022-1369 (IPCZ Trust Confusion):
- Don't trust untrusted processes: The core fix was to propagate trust information correctly through the IPCZ deserialization path. All code dealing with IPCZ messages now explicitly validates the trust level of the sender and refuses to accept or act on messages that falsely claim a trusted origin from an untrusted source. If a renderer sends bad trust data, it is killed.
- Improved IPC Message Generation and Parsing: The "1980s macro mess" for IPCZ message generation was replaced. Message shapes are now defined in data files, which are used to generate Python structs for easier packet dumping and robust message processing code. This significantly improves debuggability, allowing developers to set breakpoints in specific functions and understand message structures without manual byte-level analysis.
- Validate Enum and Bool Ranges: A critical, broader class of bugs was addressed: the compiler's assumption that enum and bool values will always be within their declared range. If an attacker sends an out-of-range enum or bool value, the compiler might generate a jump table that lands in arbitrary memory, potentially leading to arbitrary code execution. Chrome now generates code to validate all enum and bool values received over the network are within their expected ranges for IPCZ packets, similar to existing Mojo IPC checks.
General Defensive Lessons and Practices:
- Post-mortems and Follow-ups: The most emphasized takeaway is the importance of conducting thorough post-mortems after critical bugs. This involves asking "could we have known?", "how to prevent future mistakes?", "was it easy to debug?", and "what are we missing?". This process generates momentum to make broader, systemic improvements.
- Auditing for Variants: Actively searching for similar vulnerabilities or "variants" in related code paths after a fix is crucial. The second bug was a direct variant of the first, highlighting the necessity of this proactive auditing.
- Make Wrong Things Impossible: Design APIs and systems to prevent incorrect usage. Wrapping handles in C++ types that prevent pseudo-handle creation is a prime example. Crashing early when something "weird" happens (e.g., sending a thread handle to a renderer) is often better than allowing undefined behavior.
- Improve Debugging Tools and Documentation: Investing in better debugging tools (like automated message dissectors) and clear, comprehensive internal documentation (e.g., the Chromium handle one-pager) significantly reduces the time and effort required to find and fix complex bugs.
- Bug Bounty Programs (VRPs): A robust Vulnerability Rewards Program (VRP) is invaluable. Paying researchers well (over $200,000 for the second bug) and even assisting them in developing high-quality exploits encourages them to report critical bugs, even variants, directly to the vendor before they are exploited in the wild.
Key Takeaways
- Post-mortems are paramount: Fixing a bug is just the first step. A thorough, blameless post-mortem analysis (asking "why did this happen?" and "how can we prevent it from happening again?") is essential for driving systemic security improvements and leveraging the momentum of a critical incident.
- Validate everything off the wire: Never trust input from untrusted processes. This includes not just data, but also the implicit trust context, handle values (especially pseudo-handles), and even the range of enum and boolean values to prevent compiler-related arbitrary code execution.
- Understand OS API nuances: Deeply understand how underlying operating system APIs (like
DuplicateHandle) behave, especially with edge cases like pseudo-handles, as kernel shortcuts can lead to unexpected and exploitable behavior. - Reduce complexity and improve tooling: Overly complex code (like the IPCZ macros) makes debugging and auditing incredibly difficult. Investing in simpler architectures, better code generation, and specialized debugging tools (e.g., packet dumps, message dissectors) saves significant time and reduces bug density.
- The value of Bug Bounty Programs (VRPs): A well-run VRP, with generous rewards and a collaborative relationship with researchers, is critical for discovering sophisticated vulnerabilities and their variants before they are widely exploited.
- Make "wrong" things impossible: Architect systems to prevent common mistakes. This includes type-safe wrappers for sensitive objects (like handles) and adding checks that either crash early or prevent dangerous operations from ever occurring, rather than relying solely on runtime validation.
About the Speaker(s)
Alex Gough works at Google on the Chrome team, specializing in Platform Security and Security Review. His role involves ensuring the safety of the Chrome browser, particularly in how it isolates web content and handles interprocess communication. He has a deep understanding of Chrome's multi-process architecture, sandboxing mechanisms, and Windows operating system internals, as demonstrated by his detailed analysis of these complex sandbox escape vulnerabilities. Gough's talk highlights his practical experience in incident response, debugging sophisticated exploits, and driving long-term security improvements within a large-scale software project.
Reviews
Dr. Zero (Offensive Security Researcher) — STRONG ACCEPT
This is what a good incident retrospective looks like: candid about what broke, specific about why, and honest about the follow-up variant that slipped through. Gough doesn't hide behind 'we fixed it' — he walks through the debugging, the pseudo-handle kernel behavior nobody reads the docs closely enough to catch, and the IPCZ trust confusion that made the second bug possible weeks later. Real war story, real lessons.
Heather Calloway (CISO) — STRONG ACCEPT
A rare, honest look at how a major browser vendor actually responds to in-the-wild sandbox escapes — not just the patches, but the architectural reckoning. Worth your time if you're making procurement, patching, or detection investment decisions around browser security.