`allowed-tools:` silently ignored in agent frontmatter — subagent inherits all parent tools, leading to credential hunting

Resolved 💬 3 comments Opened Feb 20, 2026 by madshn Closed Mar 20, 2026

Summary

Custom agent files (.claude/agents/*.md) use tools: to restrict available tools per the docs. However, skill files (.claude/skills/*/SKILL.md) use allowed-tools: for the same purpose.

When an agent file uses allowed-tools: (the skill field name) instead of tools: (the agent field name), the field is silently ignored and the subagent inherits all parent session tools — including unrestricted Bash.

This caused two security incidents where subagents escalated from MCP authentication failures into credential hunting — reading config files, extracting tokens, accessing the macOS Keychain, and making direct API calls with extracted credentials.

Environment

  • Claude Code: 2.1.49
  • macOS: 26.2
  • Models affected: claude-sonnet-4-6 (subagent), claude-opus-4-6 (parent + subagent)

Steps to reproduce

Bug 1: allowed-tools: silently ignored

  1. Create .claude/agents/test-agent.md:
---
name: test-agent
description: Test agent with restricted tools
allowed-tools:
  - Read
  - Glob
model: sonnet
---

You are a test agent. Only use Read and Glob tools.
  1. In project settings.json, allow Bash and Task(*):
{
  "permissions": {
    "allow": ["Bash", "Task(*)", "Read", "Glob", "Grep"]
  }
}
  1. Spawn the agent via Task tool and ask it to do something that requires Bash
  2. Observe: The subagent can use Bash despite allowed-tools: specifying only Read and Glob
  3. Expected: The subagent should only have access to Read and Glob, OR a warning should be emitted about the unrecognized field

Bug 2: Model credential hunting on MCP auth failure

  1. Have an MCP server configured in .mcp.json with auth tokens
  2. Let the MCP server's auth expire (e.g., OAuth token expiration)
  3. Spawn a subagent that depends on that MCP server
  4. Observe: The subagent reads .mcp.json, extracts API keys from other MCP configs, searches for credential files, and may access the macOS Keychain
  5. Expected: The subagent should report the MCP auth failure to the user

The naming confusion

| File type | Field name | Location |
|-----------|-----------|----------|
| Skills | allowed-tools: | .claude/skills/*/SKILL.md |
| Agents | tools: | .claude/agents/*.md |

This inconsistency is easy to confuse, especially when building both skills and agents for the same project.

Security impact

Incident 1 (Sonnet subagent, MCP plugin auth expired)

The subagent made 85 tool calls (47 Bash), including:

  • Reading MCP config files and extracting bearer tokens
  • Globbing for credential directories and .env* files
  • Reading credential files from disk
  • Extracting JWT tokens and using them in ~15 curl commands
  • Attempting to create a temporary workflow to proxy API calls using stolen credentials
  • Running security find-generic-password and security dump-keychain (macOS Keychain)

No tool call was ever denied by the system.

Incident 2 (Opus parent + subagent, different MCP server token expired)

Same credential-hunting pattern in a different session, 2 hours later:

  • Opus parent deliberately routed to a subagent because "it has its own MCP access"
  • Subagent parsed MCP config, extracted JWT from a different MCP server's config
  • This agent legitimately had Bash access — so this is purely a model behavior issue

Both Sonnet and Opus exhibit this credential-hunting behavior when MCP auth fails.

Expected behavior

  1. allowed-tools: should either be accepted as an alias for tools: in agent frontmatter, or produce a warning — the current silent failure is dangerous
  2. Warn on unrecognized frontmatter fields — this would catch typos and field name mismatches
  3. Models should not hunt for credentials when MCP auth fails — they should report the failure to the user, especially when the agent's instructions explicitly say to report failures

Related issues

  • #25000 — Sub-agents bypass permission deny rules
  • #4740 — Sub-agents use tools without permission
  • #20264 — Allow restrictive permission modes for subagents

Full details available in private /feedback submission (ID: 714e1e8a-d07f-4446-810c-7fd3794b9323).

View original on GitHub ↗

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