Encrypt file-fallback session at rest with Windows DPAPI#81
Open
chirstius wants to merge 1 commit into
Open
Conversation
On Windows, Credential Manager rejects credential blobs above its size cap, so a cookie-mode session (~1 KB) can't be stored in the keyring and save_session_blob() silently falls back to a plaintext file. Encrypt that file at rest with DPAPI (CryptProtectData), scoped to the current user -- the same per-user protection Credential Manager uses, without the size cap. Legacy plaintext files are migrated transparently on load. No-op on non-Windows platforms, where the file stays as before. Refs robcerda#80
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #80.
Problem
On Windows, a cookie-mode session blob (~950 chars) exceeds Windows Credential Manager's credential-size cap, so
save_session_blob()throws, hits theexcept, and silently writes the session to a plaintext file — even though_keyring_available()(which probes with a 1-byte value) reported the keyring as usable and the logs say the keyring is in use. The result is live Monarch session cookies stored in cleartext at rest, without the user realizing it. See #80 for the full analysis and repro.Change
Encrypt the file fallback at rest on Windows using DPAPI (
win32crypt.CryptProtectData), scoped to the current user. DPAPI is the same per-user protection Credential Manager uses under the hood, but without the blob-size cap, so it comfortably holds a cookie session._dpapi_available()/_dpapi_encrypt()/_dpapi_decrypt(); encrypted values are stored asDPAPI:<base64>._save_token_file()encrypts when DPAPI is available._load_token_file()decryptsDPAPI:-prefixed content and transparently migrates any existing legacy plaintext file to encrypted on first read.pywin32(which provideswin32crypt) already ships transitively with the existing deps on Windows.This intentionally does not touch the keyring path or the
_keyring_available()probe — it only hardens the fallback that's already being used. Making the probe size-aware (so the "using keyring" log is accurate) is worth a follow-up but is orthogonal to encrypting data at rest.Testing
On Windows 11 (Python 3.13, Credential Manager backend):
~/.monarch-mcp-server/tokenauto-migrated toDPAPI:-prefixed ciphertext on load.get_accounts()call succeeds (41 accounts).Notes
Same class of platform limitation OpenAI Codex hit for Windows OAuth tokens (openai/codex#10353) — there's no way to make a large credential fit the vault, so encrypting the fallback is the practical fix.