[BUG] `--allowedTools` has no effect when permission bypass flags are active

Resolved 💬 4 comments Opened Apr 18, 2026 by KnightsofKnee Closed Jun 17, 2026

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?

--allowedTools does not restrict tool availability when used alongside --dangerously-skip-permissions or
--permission-mode bypassPermissions. The model can call any tool regardless of what's specified in the allowed list.

This means there is no secure non-interactive mode for Claude Code. Headless consumers (daemons, cron jobs, CI pipelines) require a permission bypass to avoid hanging on interactive prompts, but enabling any bypass defeats tool restrictions entirely.

What Should Happen?

--allowedTools should be enforced regardless of permission mode. Specifically:

  • Tools in the allowed list: auto-accept without prompting (non-interactive safe)
  • Tools not in the allowed list: hard-reject (return error to model, do not execute)

This would allow a secure non-interactive mode where the tool boundary is real, not advisory.

Error Messages/Logs

Steps to Reproduce

```bash
# Expected: Bash tool should be unavailable (only Read, Grep, Glob allowed)
# Actual: Bash works, model runs the command successfully

echo 'Run echo BASH_WORKS using the Bash tool' \
| claude --allowedTools "Read Grep Glob" --dangerously-skip-permissions -p

# Same result with --permission-mode:
echo 'Run echo BASH_WORKS using the Bash tool' \
| claude --allowedTools "Read Grep Glob" --permission-mode bypassPermissions -p

Both commands succeed. The model calls Bash and executes the command despite Bash not being in --allowedTools.

Claude Model

Opus

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.111

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

VS Code integrated terminal

Additional Information

Actual behavior

Both --dangerously-skip-permissions and --permission-mode bypassPermissions override --allowedTools entirely. All toolsare available regardless of the allowed list. --disallowedTools is similarly defeated.

Secondary issue: Bash command patterns are cosmetic

Separately, --allowedTools "Bash(python3:,cat:,ls:)" does not restrict which commands execute inside Bash. The pattern filter applies to tool name matching, not command content. A model given Bash(cat:) can still run sed -i, curl, rm -rf, etc.

Impact

  • No secure headless mode exists. Every non-interactive Claude Code deployment (daemons, cron, CI) has unrestricted tool access.
  • Defense-in-depth is illusory. Developers who specify --allowedTools alongside a permission bypass believe they have tool restrictions. They do not.
  • Prompt injection attack surface is maximized. Any agent processing external input (chat messages, emails, documents) with a permission bypass has no tool boundary between injected content and arbitrary code execution.

Suggested fix

A new permission mode (e.g., --permission-mode allowlistOnly) that:

  1. Does not prompt the user (works non-interactively)
  2. Auto-accepts tool calls matching --allowedTools patterns
  3. Hard-rejects tool calls not matching --allowedTools (returns error to model, does not execute)
  4. Enforces Bash command patterns as actual restrictions on command content, not just tool name matching

View original on GitHub ↗

This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗