Problem
Chrome 127 (released 2024-07-30) introduced App-Bound Encryption (ABE) on Windows. The cookie master key is now also stored as os_crypt.app_bound_encrypted_key in Local State (base64, APPB prefix), wrapped by User-DPAPI then SYSTEM-DPAPI and unwrappable only via Chrome's COM elevation service (IElevator::DecryptData).
Our Windows path only reads the legacy os_crypt.encrypted_key (DPAPI prefix) in getChromePassword.ts. On newer Chrome/Edge/Brave installs where cookies are keyed with the app-bound key, our DPAPI-only path can retrieve the wrong/missing key and fail to decrypt — silently returning empty/garbage values.
Location: src/core/browsers/chrome/windows/getChromePassword.ts:71-97
Found in: yt-dlp cross-reference + WebSearch (codebase scan)
Type: enhancement (research-heavy)
Context
Legacy path we implement:
// getChromePassword.ts — reads only the legacy DPAPI-wrapped key
const base64_key = localState.os_crypt.encrypted_key; // "DPAPI"-prefixed
ABE adds os_crypt.app_bound_encrypted_key (APPB-prefixed) which requires the elevation COM service to unwrap. yt-dlp does not implement ABE either (its Windows decryptor only does DPAPI + AES-GCM v10) — so implementing this puts get-cookie ahead of the reference.
Research Findings
- ABE wraps the key User-DPAPI → SYSTEM-DPAPI; decryption is delegated to a COM elevation service running as SYSTEM. The
APPB blob is passed to IElevator::DecryptData, returning a 32-byte AES key (the app_bound_key).
- Pure user-mode Node decryption is non-trivial; options: (a) invoke the elevation COM interface via a native addon, (b) detect ABE and degrade gracefully with a clear diagnostic, (c) optional helper binary.
- A partial Chrome mitigation exists but is disabled by default (as of mid-2025).
- Sources:
- Complexity: Complex.
Recommended Approach
- Detect
app_bound_encrypted_key (APPB prefix) in Local State; log a clear, actionable message when present and the legacy key is absent/failing.
- Phase 1 (graceful): when only the ABE key is available, surface a precise warning/error (not silent empty values) and document the limitation.
- Phase 2 (full): evaluate a Windows-only optional native binding for
IElevator::DecryptData to obtain the app-bound key, then reuse the existing AES-GCM v10 path (including the hash-prefix fix from the sibling Windows issue).
- Add fixtures for
Local State containing both encrypted_key and app_bound_encrypted_key.
Acceptance Criteria
Problem
Chrome 127 (released 2024-07-30) introduced App-Bound Encryption (ABE) on Windows. The cookie master key is now also stored as
os_crypt.app_bound_encrypted_keyinLocal State(base64,APPBprefix), wrapped by User-DPAPI then SYSTEM-DPAPI and unwrappable only via Chrome's COM elevation service (IElevator::DecryptData).Our Windows path only reads the legacy
os_crypt.encrypted_key(DPAPIprefix) ingetChromePassword.ts. On newer Chrome/Edge/Brave installs where cookies are keyed with the app-bound key, our DPAPI-only path can retrieve the wrong/missing key and fail to decrypt — silently returning empty/garbage values.Location:
src/core/browsers/chrome/windows/getChromePassword.ts:71-97Found in: yt-dlp cross-reference + WebSearch (codebase scan)
Type: enhancement (research-heavy)
Context
Legacy path we implement:
ABE adds
os_crypt.app_bound_encrypted_key(APPB-prefixed) which requires the elevation COM service to unwrap. yt-dlp does not implement ABE either (its Windows decryptor only does DPAPI + AES-GCM v10) — so implementing this puts get-cookie ahead of the reference.Research Findings
APPBblob is passed toIElevator::DecryptData, returning a 32-byte AES key (theapp_bound_key).Recommended Approach
app_bound_encrypted_key(APPBprefix) inLocal State; log a clear, actionable message when present and the legacy key is absent/failing.IElevator::DecryptDatato obtain the app-bound key, then reuse the existing AES-GCM v10 path (including the hash-prefix fix from the sibling Windows issue).Local Statecontaining bothencrypted_keyandapp_bound_encrypted_key.Acceptance Criteria
Local Stateparsing recognizesapp_bound_encrypted_keyand itsAPPBprefix.