From 80dfc988a13b73c85e48ef2b59444a6b2cac003c Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Tue, 21 Apr 2026 20:42:15 -0700 Subject: [PATCH] security(N2): document Windows v20 ABE elevation path on CDP port The existing comment around the cookie-import-browser --remote-debugging-port launch claimed "threat model: no worse than baseline." That's wrong on Windows with App-Bound Encryption v20. A same-user local process that opens the cookie SQLite DB directly CANNOT decrypt v20 values (DPAPI context is bound to the browser process). The CDP port lets them bypass that: connect to the debug port, call Network.getAllCookies inside Chrome, walk away with decrypted v20 cookies. The correct fix is to switch from TCP --remote-debugging-port to --remote-debugging-pipe so the CDP transport is a stdio pipe, not a socket. That requires restructuring the CDP WebSocket client in this module and Playwright doesn't expose the pipe transport out of the box. Non-trivial, deferred from the v1.6.0.0 wave. This commit updates the comment to correctly describe the threat and points at the tracking issue. No code change to the launch itself. Follow-up: #1136. Co-Authored-By: Claude Opus 4.7 (1M context) --- browse/src/cookie-import-browser.ts | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/browse/src/cookie-import-browser.ts b/browse/src/cookie-import-browser.ts index 271d3659..66328432 100644 --- a/browse/src/cookie-import-browser.ts +++ b/browse/src/cookie-import-browser.ts @@ -831,15 +831,28 @@ export async function importCookiesViaCdp( // Launch Chrome headless with remote debugging on the real profile. // // Security posture of the debug port: - // - Chrome binds --remote-debugging-port to 127.0.0.1 by default. We rely - // on that — the port is NOT exposed to the network. Any local process - // running as the same user could connect and read cookies, but if an - // attacker already has local-user access they can read the cookie DB - // directly. Threat model: no worse than baseline. + // - Chrome binds --remote-debugging-port to 127.0.0.1 by default. The + // port is NOT exposed to the network. Baseline threat: a local + // process running as the same user can connect. // - Port is randomized in [9222, 9321] to avoid collisions with other - // Chrome-based tools the user may have open. Not cryptographic. + // Chrome-based tools. Not cryptographic — security relies on + // same-user-access baseline, not port secrecy. // - Chrome is always killed in the finally block below (even on crash). // + // KNOWN NON-GOAL (tracked as a separate hardening task for the next + // security wave): + // On Windows 10.15+ with App-Bound Encryption (v20) enabled, a + // same-user process that opens the cookie DB directly cannot decrypt + // v20 values — the DPAPI context is bound to the browser process. + // The CDP port bypasses that: `Network.getAllCookies` runs inside the + // browser, so any same-user process that connects to the debug port + // before we kill Chrome could exfiltrate decrypted v20 cookies. + // Fix direction: switch to `--remote-debugging-pipe` so the CDP + // transport is a parent/child stdio pipe, not TCP. Requires + // restructuring the extractCookiesViaCdp WebSocket client; deferred + // to a follow-up because the transport swap is non-trivial and the + // baseline threat is still "attacker already has same-user access." + // // Debugging note: if this path starts failing after a Chrome update, // check the Chrome version logged below — Chrome's ABE key format (v20) // or /json/list shape can change between major versions.