Bash permissions.deny rules not enforced in subagent (Agent/Task tool) shells — denied command executes, only post-hoc security warning

Status Fixed / completed
Reported on v2.1.214
Maintainer reply ✓ Yes — bcherny
Activity 4 comments · opened Jul 18, 2026 · closed Aug 17, 2026
💡 Likely answer: A maintainer (bcherny, collaborator) responded on this thread — see the highlighted reply below.

Summary

A permissions.deny Bash rule that is correctly enforced in the main conversation loop is not enforced inside a subagent spawned via the Agent (Task) tool. The subagent executed the denied command successfully; the only trace was a post-hoc SECURITY WARNING in the parent's task-notification saying the command "matches the user's configured deny rule … this command should not have executed".

Environment

  • Claude Code 2.1.214 (CLI), macOS (darwin 25.5.0)
  • Project .claude/settings.json:
"permissions": {
  "deny": [
    "Bash(git stash)",
    "Bash(git stash:*)",
    "Bash(rtk git stash)",
    "Bash(rtk git stash:*)"
  ]
}

What happened

  1. Main loop: a Bash call containing rtk git stash list was denied as expected ("Permission to use Bash with command … has been denied."). Enforcement works there — including the compound-command case.
  2. A background subagent (Agent tool, subagent_type: general-purpose, model sonnet) working in the same project ran:

``
git stash push -u -m "wip: issue-1505 checked-op fix + tests"
``

The command executed (the stash was created and later consumed; work was recoverable, no data loss in this instance).

  1. The parent session's task-completion notification carried:

> SECURITY WARNING: This subagent performed actions that may violate security policy. Reason: [User Deny Rules] The subagent ran git stash push -u -m "wip: …", which matches the user's configured deny rule Bash(git stash:*) — this command should not have executed…

So a detection layer recognizes the violation post-hoc, but the PreToolUse permission gate that blocks the command in the main loop did not fire (or did not deny) in the subagent context.

Expected

Deny rules are a security boundary; they should bind every Bash execution in the session, including subagent (Task/Agent) contexts — same as the main loop. Post-hoc warning is detection, not prevention: for destructive commands (git reset --hard, rm, …) the damage is done by the time the parent is told.

Repro sketch

  1. Add "Bash(git stash:*)" to permissions.deny in project .claude/settings.json.
  2. Confirm the main loop refuses git stash list.
  3. Spawn a Task/Agent subagent whose work plausibly leads it to stash (e.g. "commit your work; keep the tree clean"), or that is directly told to run git stash push.
  4. Observe the subagent executes it; the parent later receives the SECURITY WARNING in the task notification.

View original on GitHub ↗

3 Comments

andrebrait · 2 months ago

Duplicate sweep before/after filing: closest existing reports are #54898 (per-agent permission scoping feature request, not deny enforcement) and #11226 (deny bypass via Edit/Write on hook files — same theme, different tool surface). Neither covers Bash deny rules not binding subagent shells, so this report stands alone.

bcherny collaborator · 1 month ago

Tried to reproduce this on 2.1.233 (Linux, fresh install, project .claude/settings.json with "deny": ["Bash(touch /tmp/denied-*)", "Bash(git stash)", "Bash(git stash:*)"]):

  • Main conversation: touch /tmp/denied-main → denied ✅
  • Subagent spawned via the Agent tool running touch /tmp/denied-sub → denied inside the subagent ("Permission to use Bash with command touch /tmp/denied-sub has been denied"), file never created ✅
  • Subagent running git stash → denied, no stash created ✅
  • Compound form cd /tmp && touch /tmp/denied-… → also denied ✅

So on the current release, permissions.deny Bash rules are enforced in subagent shells the same as in the main conversation — I couldn't reproduce what you saw on 2.1.214. This appears to have been resolved in a recent release (changelog).

Closing — if you still see this on the latest version, please reply to reopen and include the subagent's exact Bash command string from its transcript (a differently phrased command, e.g. wrapped in sh -c or prefixed with other commands, is the detail we'd need).

🤖 Generated with Claude Code

github-actions[bot] · 1 month ago

We weren't able to reproduce this. Could you provide steps to trigger the issue — what you ran, what happened, and what you expected? This issue will be closed automatically if there's no activity within 7 days.

Showing cached comments. Read the full discussion on GitHub ↗