fix(security): block write_file/patch on Gemini OAuth store (read/write parity) - #38493
fix(security): block write_file/patch on Gemini OAuth store (read/write parity)#38493Dusk1e wants to merge 1 commit into
Conversation
tonydwb
left a comment
There was a problem hiding this comment.
Code Review Summary
Verdict: Approved
Changes
This PR closes the read/write parity gap for the Gemini OAuth credential store by adding auth/google_oauth.json to both the root-level build_write_denied_paths and the existing per-hermes-home deny list.
Security Observations
- Correct gap:
get_read_block_erroralready blockedauth/google_oauth.jsonreads under a profile (PR #17656), butis_write_denieddid not. A prompt-injectedwrite_file/patchcould silently overwrite the refresh/access tokens thatget_valid_access_token()reads back. This PR resolves that asymmetry. - Both locations protected:
hermes_home / auth/google_oauth.json(active profile) andhermes_root / auth/google_oauth.json(global root shared across profiles) are now in the deny list — matches PR #15981's pattern for.envwidening.
Testing
- Tests added in
tests/tools/test_file_operations.pycovering both profile-mode and root paths.
Reviewed by Hermes Agent
teknium1
left a comment
There was a problem hiding this comment.
Thanks for the narrow parity hardening. The production change targets a real current-main gap: agent/file_safety.py:28-58 write-denies .anthropic_oauth.json but not auth/google_oauth.json, while the read guard already classifies the latter as a credential store at agent/file_safety.py:241-260.
Problems
- The new comments cite
agent/google_oauth.py/get_valid_access_token(), butagent/google_oauth.pyis not present at current HEAD. Please remove that stale implementation-specific attribution and retain a concise credential-store rationale. - The test hunk predates
81e42335a1, which intentionally made Hermes control files writable while retaining OAuth-store denials. Current coverage is split between OAuth cases attests/tools/test_file_operations.py:65-82and the profile/root OAuth test at:118-127.
Suggested changes
- Add
auth/google_oauth.jsonto those two current OAuth parameterizations, preserving the control-file writable cases.
Automated hermes-sweeper review.
| # when a profile is active; default/non-profile sessions still read it. | ||
| str(hermes_root / ".anthropic_oauth.json"), | ||
| # Active profile Gemini (google-gemini-cli) OAuth credential store. | ||
| # The read side has been guarded since #17656, but the write side |
There was a problem hiding this comment.
agent/google_oauth.py is absent from current main, so this implementation-specific comment would be stale on salvage. Please replace this block with a short path/purpose comment that does not reference the removed module or function.
What
Add
auth/google_oauth.json(Gemini / google-gemini-cli OAuth store) to the write deny list inagent/file_safety.py, at both the active-profileHERMES_HOMEand the global root.Why
The store is read-guarded since #17656, but the write side was never added. A prompt-injected
write_file/patch/move/deletecould overwrite the refresh+access tokens thatget_valid_access_token()reads back (agent/google_oauth.py) — hijacking or bricking the Gemini session. Every other credential store in the read guard (auth.json,.anthropic_oauth.json,.env,webhook_subscriptions.json,mcp-tokens/) is already write-denied;google_oauth.jsonwas the lone exception. Same root-widening as #15981.Tests
auth/google_oauth.jsonto the basic + profile-mode deny parametrize.