Session-level permission caching bypasses allow list for Bash commands when sandbox mode is enabled
Bug Description
When sandbox mode is enabled, approving a Bash command that is not in the permissions.allow list causes the approval to be cached for the remainder of the session. Subsequent invocations of matching commands execute without prompting, even though they were never pre-approved.
This worked correctly before enabling sandbox mode — every invocation prompted as expected.
Steps to Reproduce
- Enable sandbox mode in
~/.claude/settings.json("sandbox": { "enabled": true, ... }) - Configure
Bash(git commit *)to be absent from bothpermissions.allowandpermissions.deny - Start a new session
- Use a skill/command that triggers
git commit— Claude Code correctly prompts for approval - Approve the commit
- Later in the same session, Claude invokes
git commitagain (different context, different files) - Expected: Claude Code prompts for approval again
- Actual: The commit executes without prompting
Environment
- Claude Code version: 2.1.86
- OS: Linux (WSL2) 5.15.167.4-microsoft-standard-WSL2
- Shell: bash
Settings Context
{
"sandbox": {
"enabled": true,
"filesystem": {
"allowWrite": ["/tmp", "~/.local/share/pnpm", "~/.npm", "~/.yarn", "~/.bun/install"],
"denyRead": ["~/.ssh", "~/.gnupg", "~/.aws/credentials"],
"denyWrite": ["~/.ssh", "~/.gnupg", "~/.bashrc", "~/.zshrc", "~/.profile"]
},
"network": {
"allowedDomains": ["github.com"],
"allowUnixSockets": ["~/.ssh/agent.sock"]
}
},
"permissions": {
"allow": [
"Bash(git status:*)",
"Bash(git add:*)",
"Bash(git push:*)",
"Bash(git diff:*)",
"Bash(git log:*)"
],
"deny": [
"Bash(*&& git commit*)",
"Bash(*; git commit*)",
"Bash(*| git commit*)"
]
}
}
Note: Bash(git commit *) is intentionally not in the allow list. The deny list only covered chained variants. Despite this, after a single approval during a /commit skill invocation, all subsequent standalone git commit calls in the session were auto-approved.
Session Transcript Evidence
Inspecting the session JSONL, all three git commit tool results show permissionBehavior: NONE — no permission prompt was triggered for any of them, including the second and third commits which were invoked outside the original /commit skill context.
Impact
This is a permission escalation within a session. Users configure allow/deny lists to maintain control over destructive or irreversible operations. A one-time approval for a specific commit should not blanket-approve all future commits in the session.
Suspected Cause
The sandbox execution path may cache command approvals differently than the standard Bash permission system. Before sandbox mode was enabled, the same configuration correctly prompted for every git commit invocation.
Workaround
Adding Bash(*git commit*) to permissions.deny hard-blocks all commit commands, but this silently denies rather than prompting — overly restrictive for users who want case-by-case approval.
Expected Behavior
Commands not in permissions.allow should prompt for approval every time, regardless of prior approvals in the same session. Sandbox mode should not alter this behavior.
This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗