disallowedTools and allowedTools not enforced for plugin-installed agents
Bug: disallowedTools and allowedTools not enforced for plugin-installed agents
Claude Code version: 2.1.126
Platform: macOS (Darwin 24.6.0)
Summary
Agent frontmatter fields disallowedTools and allowedTools are enforced for local agents (.claude/agents/*.md) but completely ignored for plugin-installed agents. A plugin agent with disallowedTools: [Bash(find *), EnterPlanMode] can still use find and enter plan mode.
Reproduction
Minimal reproduction with two identical agents - one local, one from a plugin.
1. Create test project
mkdir -p /tmp/disallowed-test/.claude/agents
cd /tmp/disallowed-test
git init
echo "# Test" > README.md
Add settings.json that allows the tools (so the test is about agent-level restrictions, not session permissions):
mkdir -p .claude
cat > .claude/settings.json << 'EOF'
{
"permissions": {
"allow": [
"Read", "Edit", "Write", "Glob", "Grep",
"Bash(find *)", "Bash(grep *)", "Bash(cat *)", "Bash(ls *)"
]
}
}
EOF
2. Create local agent
cat > .claude/agents/local-test.md << 'EOF'
---
name: local-test
description: Test agent with restricted tools
tools: Read, Agent
allowedTools:
- Read
- Agent
disallowedTools:
- Bash(find *)
- Bash(grep *)
- Bash(cat *)
- Bash(ls *)
- Edit
- Write
- Glob
- Grep
- EnterPlanMode
- ExitPlanMode
---
Try these commands directly (do NOT spawn subagents):
1. Run `find . -name "*.md"` via Bash
2. Run `ls .` via Bash
3. Enter plan mode
Report which ones were blocked.
EOF
3. Create identical plugin agent
mkdir -p /tmp/test-plugin/.claude-plugin /tmp/test-plugin/agents
cat > /tmp/test-plugin/.claude-plugin/plugin.json << 'EOF'
{
"name": "test-restricted",
"description": "Test plugin"
}
EOF
cat > /tmp/test-plugin/.claude-plugin/marketplace.json << 'EOF'
{
"$schema": "https://anthropic.com/claude-code/marketplace.schema.json",
"name": "test-restricted",
"description": "Test plugin",
"owner": { "name": "test" },
"plugins": [{ "name": "test-restricted", "source": "./", "category": "productivity" }]
}
EOF
# Same agent definition, different name
cat > /tmp/test-plugin/agents/plugin-test.md << 'EOF'
---
name: plugin-test
description: Test agent with restricted tools
tools: Read, Agent
allowedTools:
- Read
- Agent
disallowedTools:
- Bash(find *)
- Bash(grep *)
- Bash(cat *)
- Bash(ls *)
- Edit
- Write
- Glob
- Grep
- EnterPlanMode
- ExitPlanMode
---
Try these commands directly (do NOT spawn subagents):
1. Run `find . -name "*.md"` via Bash
2. Run `ls .` via Bash
3. Enter plan mode
Report which ones were blocked.
EOF
cd /tmp/test-plugin && git init && git add -A && git commit -m "init"
4. Install plugin and add marketplace
claude plugin marketplace add /tmp/test-plugin
claude plugin install test-restricted
5. Run both agents from the same directory
cd /tmp/disallowed-test
# Test 1: local agent
claude --agent local-test "Try all 3 commands directly and report which were blocked."
# Test 2: plugin agent
claude --agent plugin-test "Try all 3 commands directly and report which were blocked."
Expected behavior
Both agents have identical disallowedTools configuration. Both should block find, ls, and EnterPlanMode.
Actual behavior
Local agent (local-test): All 3 commands blocked. Agent reports "No Bash tool available." Correct.
Plugin agent (plugin-test): All 3 commands succeed. find returns file list, ls works, EnterPlanMode enters plan mode. disallowedTools is completely ignored.
Impact
This makes it impossible to create plugin agents with restricted tool access. For example, a dispatcher agent that should only use Read and Agent (never Edit, Write, or EnterPlanMode) has full tool access when installed as a plugin, breaking the intended architecture.
Additional finding
In a separate test, a local agent's disallowedTools are enforced on the agent itself, but spawned general-purpose subagents do NOT inherit the parent's restrictions. The subagent gets full session permissions. This may be by design, but worth noting.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗