[BUG] Invalid settings file silently drops `permissions.deny`/`ask` rules mid-session (fail-open)
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
While a session is running, if a watched settings file becomes syntactically
invalid (e.g. an intermediate save during hand-editing), the file is rejected
as a whole and its permissions.deny / permissions.ask rules silently stop
being enforced. A command that was deterministically denied seconds earlier
runs with no prompt and no warning. Enforcement returns only once the file
parses again.
The docs say an invalid settings file is "rejected as a whole and reported",
but do not say the rejection is fail-open, and in print/stream-json mode
nothing is reported at all — the only symptom is that guardrails vanish.
What I observed
During a long interactive session, I had these settings:
defaultMode: "auto"permissions.askincluding"Bash(git push:*)"- model: Fable 5
I made some invalid hand edits to ~/.claude/settings.json. Multiple git push * commands were auto-approved while it was invalid.
The only indicator I had that something was wrong was that my custom spinnerVerbs was not being respected.
What Should Happen?
Either keep enforcing the last-known-good rules until the file parses again (fail-closed), or at minimum surface a prominent, blocking warning that permission rules from that file are no longer in effect (mirroring the error shown when starting a new claude session).
Silent fail-open turns a typo during a settings edit into an enforcement gap for every concurrently running session that watches the file.
Error Messages/Logs
Steps to Reproduce
mkdir -p repro/.claude && cd repro
printf '{"permissions":{"deny":["Bash(uname:*)"]}}' > .claude/settings.json
Drive one session across turns with stream-json input:
claude -p --input-format stream-json --output-format stream-json \
--verbose --model haiku --max-turns 12
Send this user message (as {"type":"user","message":{"role":"user","content":[{"type":"text","text":"..."}]}})
for each turn, mutating the settings file between turns:
Run this exact bash command: uname — then report what happened. If the tool call is denied or blocked, reply with only BLOCKED plus the denial text. Do not try alternatives or workarounds.
| Turn | settings.json state | Result |
|------|----------------------------------------------|---------------------------------|
| 1 | valid, deny present | denied (correct) |
| 2 | invalid JSON (trailing { appended) | uname executes — fail-open|
| 3 | valid, deny removed | executes (proves hot-reload live)|
| 4 | valid, deny restored | denied (recovery works) |
Claude Model
Other
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.214
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
VS Code integrated terminal
Additional Information
- #78056 documents the same whole-file-discard behavior. However, that issue is about _how_ the settings file gets corrupted. This issue is about how to securely inform the use of the effects of the corruption.
- #42797 is about how
permissions.askis applied in auto-mode. But it doesn't address invalidsettings.jsonfiles. - #62506 is similar, but focuses on intentional/malicious, valid changes to settings files.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗