Skip to content

Windows: Chrome 127+ App-Bound Encryption stores GitHub cookies as v20, which kooky cannot decrypt #4

@drogers0

Description

@drogers0

Windows: Chrome 127+ App-Bound Encryption stores GitHub cookies as v20, which kooky cannot decrypt

Summary

On Windows, default Chrome 127+ stores the GitHub user_session cookie using App-Bound Encryption (v20). gh-image relies on kooky to read and decrypt Chromium-family cookies, but kooky v0.2.9 does not support v20 ABE on Windows.

As a result, gh-image fails even when the GitHub session is present and Chrome is closed.

This is a decryption problem, not an upload problem.

Environment

  • OS: Windows
  • Browser: Chrome with an active GitHub session
  • Command:
gh image C:\path\to\image.png --repo owner/repo

Expected Behavior

gh-image should be able to read the GitHub user_session cookie from Chrome and continue with the upload flow.

Actual Behavior

The command fails because the cookie is present but cannot be decrypted:

Error: cannot decrypt Chrome cookies — Chrome 127+ uses App-Bound Encryption (ABE) on Windows which is not yet supported.

Reproduction

  1. Use Windows with default Chrome security settings.
  2. Ensure Chrome has an active GitHub session.
  3. Leave Chrome either open or closed.
  4. Run:
gh image C:\path\to\image.png --repo owner/repo

Observed result:

  • gh-image fails because Chrome stores the relevant GitHub cookie as v20 and kooky cannot decrypt it.

Diagnostic Findings

Inspection of Chrome's cookie DB showed:

Cookie: host=github.com name=user_session
Encrypted prefix (ascii): v20
-> Encryption: v20 App-Bound Encryption (Chrome 127+)

Other GitHub session-related cookies were also v20:

github.com / user_session : enc_len=111 prefix=v20
github.com / __Host-user_session_same_site : enc_len=111 prefix=v20

kooky v0.2.9 detects v20 but does not implement Windows decryption for it. In practice, this means gh-image cannot read the session cookie from a default Chrome 127+ Windows profile.

Why this happens

Chrome 127+ uses App-Bound Encryption on Windows to bind access to browser-stored secrets more tightly to Chrome itself. This changes the decryption model compared to earlier cookie formats such as v10.

That is a Chrome/browser-layer change, not a GitHub-specific change.

Workarounds and Mitigations

Workaround 1: locally prototyped GH_IMAGE_COOKIE escape hatch

A local prototype added support for setting the GitHub user_session cookie directly:

set GH_IMAGE_COOKIE=<paste-user_session-cookie-value>
gh image C:\path\to\image.png --repo owner/repo

How to get the value:

  1. Open Chrome and go to https://github.com
  2. Open DevTools
  3. Go to Application > Cookies > https://github.com
  4. Copy the user_session cookie value

Pros:

  • Works immediately
  • Avoids all browser decryption issues

Cons:

  • Manual
  • Cookie must be refreshed when the GitHub session rotates

This is not assumed to exist in the unmerged upstream state. It is included here as a concrete, low-risk mitigation that was validated locally.

Workaround 2: Disable ABE, then refresh GitHub cookies

Disable ABE via policy:

reg add "HKLM\Software\Policies\Google\Chrome" /v ApplicationBoundEncryptionEnabled /t REG_DWORD /d 0 /f

Important: this is not retroactive.

After the policy change, the user must:

  1. Restart Chrome
  2. Sign out of GitHub and sign back in, or clear github.com cookies and log in again

Only then do the relevant GitHub cookies get reissued as v10.

Verified post-refresh cookie state:

github.com / __Host-user_session_same_site : enc_len=111 prefix=v10
.github.com / dotcom_user : enc_len=71 prefix=v10
.github.com / logged_in : enc_len=66 prefix=v10
github.com / saved_user_sessions : enc_len=123 prefix=v10
github.com / user_session : enc_len=111 prefix=v10

Pros:

  • Restores automatic cookie reading for the relevant GitHub session cookies

Cons:

  • Requires admin access
  • Weakens Chrome's Windows local-data protections
  • Does not rewrite existing cookies until they are reissued

Alternative Package / Tool Options

1. Stay on kooky, improve messaging and fallback behavior

This is the least invasive path. A local prototype showed that two small changes materially improve the situation:

  • a clearer Windows ABE error message
  • GH_IMAGE_COOKIE support as a manual bypass

These do not solve v20, but they make the tool recoverable for affected Windows users.

2. CookieKatz / ChromeKatz family

Potential Windows-only fallback:

  • Read decrypted cookies from Chrome process memory instead of the on-disk cookie DB
  • This bypasses v20 decryption limitations entirely

Pros:

  • Can work even when Chrome uses ABE

Cons:

  • High maintenance cost
  • Likely AV / EDR friction
  • Requires shipping or invoking a separate binary
  • More invasive than the current model

3. DevTools Protocol fallback

If Chrome is started with remote debugging enabled, it may be possible to read cookies through DevTools Protocol.

Pros:

  • Official browser surface

Cons:

  • Not enabled by default
  • Adds setup / operational complexity

Proposed Fixes

Short-term

  1. Add GH_IMAGE_COOKIE support as an escape hatch
  2. Add an explicit Windows ABE error message
  3. Document that disabling ABE requires cookie refresh / reauthentication before it helps

Long-term

  1. Revisit this if kooky gains v20 support
  2. Evaluate whether a Windows-only fallback like CookieKatz / ChromeKatz is acceptable
  3. Evaluate a DevTools Protocol fallback if a debug port is present

Acceptance Criteria

  • On Windows with default Chrome 127+ settings, users get a clear, actionable error rather than an opaque failure.
  • A documented escape hatch exists for users who need to supply the session cookie manually.
  • If ABE is disabled and GitHub cookies are refreshed, the decryption-specific issue is resolved.

Notes

  • This issue is distinct from the separate Windows problem where cookie-store access may still fail while Chrome is running.
  • The upload protocol is not the problem. Once a valid GitHub session cookie is available, uploads succeed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions