[SECURITY] PreToolUse hooks not enforced on subagent tool calls, allowing security bypass

Resolved 💬 15 comments Opened Jan 28, 2026 by allannapier Closed May 29, 2026

Summary

PreToolUse hooks configured in ~/.claude/settings.json are not enforced when subagents spawned via the Task tool make their own tool calls. This creates a security vulnerability where restrictions that apply to the main agent can be completely bypassed by spawning a subagent.

Steps to Reproduce

  1. Configure a PreToolUse hook to restrict file writes outside the project directory:
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write|Edit|Bash",
        "hooks": [
          {
            "type": "command",
            "command": "~/.claude/hooks/restrict-operations.py",
            "timeout": 5
          }
        ]
      }
    ]
  }
}
  1. Hook script blocks writes outside project directory (exits with code 1 for unauthorized paths)
  1. Try to write a file outside project with main agent:
  • Correctly blocked by PreToolUse hook
  1. Spawn a subagent with the same request:
Task tool with python-coder subagent
Prompt: "Create a file at /Users/username/test.py"
  • Bypasses the hook - file is created successfully

Expected Behavior

PreToolUse hooks should apply recursively to all agents in the execution tree:

  • Main agent's tool calls → hook enforced
  • Subagent's tool calls → hook enforced
  • Sub-subagent's tool calls → hook enforced

Actual Behavior

PreToolUse hooks only apply to the agent where settings.json is loaded:

  • Main agent's tool calls → hook enforced ✅
  • Subagent's tool calls → hook NOT enforced ❌

Security Impact

This allows complete bypass of security restrictions:

  1. File access controls - Can write/read files anywhere on the system
  2. Command restrictions - Can execute unrestricted bash commands
  3. Self-modification - Can modify or delete the hooks themselves
  4. Privilege escalation - Any security boundary can be bypassed

Attempted Workarounds

1. SubagentStart Hook

Added SubagentStart hook to intercept subagent spawning and analyze prompts for suspicious patterns. Limitation: Can only do heuristic analysis of the prompt text, cannot actually enforce tool-level restrictions within the subagent.

2. Intercept Task Tool

Added Task tool to PreToolUse matcher to block suspicious subagent prompts. Limitation: Prompt analysis is unreliable - many legitimate prompts contain file paths, and adversarial prompts can obfuscate intent.

Proposed Solutions

  1. Global Hook Enforcement (Preferred)
  • Hooks configured in ~/.claude/settings.json should apply system-wide to all agents
  • Each subagent inherits parent's hook configuration
  • Hooks execute in subagent's context when subagent makes tool calls
  1. Explicit Hook Inheritance Flag
  • Add inherit: true option to hook configuration
  • Allows opt-in recursive enforcement for security-critical hooks
  1. Subagent Security Context
  • Add security context parameter to Task tool
  • Explicitly declare which hooks must be enforced on subagent

Environment

  • Platform: macOS (Darwin 25.2.0)
  • Claude Code Version: Latest (using claude-sonnet-4-5-20250929)
  • Hook Types Affected: PreToolUse
  • Tools Affected: Write, Edit, Bash, NotebookEdit (any tool called by subagents)

Related Issues

  • #20221 - SubagentStop hooks don't prevent termination
  • #16424 - Expose Agent Context in Hook Event Payloads
  • #16126 - Add agent identity to PreToolUse hook data
  • #18653 - Tool result transform hook for content sanitization

Example Use Cases Requiring This Fix

  1. Corporate environments - Enforce write restrictions to prevent data exfiltration
  2. Sandboxed execution - Prevent agents from escaping sandbox via subagents
  3. Code review automation - Ensure read-only analysis can't be bypassed
  4. Credential protection - Block access to sensitive files/directories
  5. Audit logging - Ensure all tool calls are logged, not just main agent

Additional Context

This is a fundamental security architecture issue. While hooks provide excellent visibility and control for the main agent, the lack of recursive enforcement makes them insufficient for security-critical use cases. Any security boundary enforced via hooks can be trivially bypassed by using the Task tool.

View original on GitHub ↗

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