feat(security): deny writes to secondary shell startup files and global git config (Claude Code v2.1.160-inspired) - #45293
Conversation
|
Verification review — This PR was reviewed as part of a scheduled code review pass. What was checked:
Verdict: Clean security hardening. The attack surface reduction is well-scoped — blocks secondary shell startup files that are equivalent persistence vectors to |
Block write tool edits to secondary shell startup files and global git config paths while preserving project-local `.git/config` writes.
d756b7f to
e2d80b6
Compare
|
Refreshed against current Cleanup:
Validation:
|
🔎 Lint report:
|
|
Closing per maintainer policy direction: Hermes should not keep expanding hardcoded write-deny lists for user-owned shell/Git config files. If users want filesystem containment, the intended boundary is Docker/remote backends, OS users, and permissions. Follow-up PR #45947 moves policy the other way by making shell startup files, package-manager configs, and Hermes control files writable again while keeping narrower blocks for SSH keys, .env/OAuth token stores, mcp-tokens, pairing state, and privileged system files. |
Summary
Writes to secondary shell startup files (
~/.zshenv,~/.zlogin,~/.bash_login) and global git config (~/.gitconfig,~/.config/git/) are now denied by the shared file-safety layer — closing the same persistence/code-execution gap Claude Code patched in v2.1.160.Source
Claude Code changelog v2.1.160–2.1.161 (Jun 2, 2026): "Security: prompt before writing shell startup files (
.zshenv,.bash_login) and~/.config/git/" — https://code.claude.com/docs/en/changelogHow our implementation differs
agent/file_safety.py), consistent with our existing.bashrc/.zshrchandling~/.config/git/~/.gitconfig(classic location) and~/.zlogin.git/configWhy hard-deny instead of prompt: hermes already hard-denies the primary startup files (
.bashrc,.zshrc,.profile, ...) viabuild_write_denied_paths(); the new entries are the same vector through less common files, so they get the same treatment. As documented infile_safety.py, this is defense-in-depth, not a security boundary — the terminal tool can still touch these with explicit shell commands (which go through dangerous-command approval).Changes
agent/file_safety.py: +4 exact deny paths (.zshenv,.zlogin,.bash_login,.gitconfig), +1 prefix deny (~/.config/git/)tools/skills_guard.py:zshenvadded to theshell_rc_modpersistence regextests/tools/test_write_deny.py: new paths covered + project-local.git/configstays writableValidation
tests/tools/test_write_deny.py+ 4 sibling file-safety test fileswrite_file_toolwith real imports, isolatedHERMES_HOME).git/configstill work