[BUG] claude should not be allowed to start claude. (Denial of service vulnerability: exploit with prompt: "sessions")

Status Fixed / completed
Maintainer reply None cached
Activity 3 comments · opened Apr 18, 2026 · closed Apr 18, 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?

Claude Code has a CLI argument "prompt" which gets sent to anthropic to figure out what to do...

Usage: claude [options] [command] [prompt]

Claude Code - starts an interactive session by default, use -p/--print for non-interactive output

Arguments:
  prompt                                            Your prompt

My copy of Claude figured out it can skip permissions checks using the Bash tool and execute Bash(claude --permission-mode auto <prompt>)...

And proceeded to fork bomb me with a few hundred variations of a prompt within a minute, using up my window of tokens. The prompt "sessions" proceeded to repeatedly fire increasingly complex bash tool uses of this prompt and let them be background tasks so that it could do more than one at a time...

What Should Happen?

The Bash tool and the new PowerShell tool should not be allowed to start Claude Code. It should be denied in all permission modes including plan, auto and yolo mode.

At the very least there should be an environment variable injected to both of these tools that forces any started claude instances to be denied access to these two tools (and maybe a few others like Write).

Error Messages/Logs

Steps to Reproduce

I am not sure exactly how I got claude to know it can start claude by passing --permission-mode auto to bypass permissions. I'd guess it is somewhere in my system memory or claude.md. However I am able to reliably reproduce it by adding to my settings.json (to prevent it from spending all of my tokens so that I can see the prompt working):

{
  "permissions": {
    "defaultMode": "auto"
  },
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "bash -c 'if echo \"$CLAUDE_TOOL_INPUT\" | jq -r .command | grep -qE \"(^|[;&|\\s])claude(\\s|$)\"; then echo \"BLOCK: Cannot invoke claude from within claude\" >&2; exit 2; fi'"
          }
        ]
      }
    ]
  },
  "skipAutoPermissionPrompt": true
}

I also don't know why claude is reliably hallucinating that it has a "sessions' subcommand.

  1. prompt: sessions

Claude Model

Opus

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

v2.1.107

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

Windows Terminal

Additional Information

C:\Repos>claude --resume
▐▛███▜▌   Claude Code v2.1.107
▝▜█████▛▘  Opus 4.6 (1M context) with high effort · Claude Team
  ▘▘ ▝▝    C:\Repos

❯ sessions

● Bash(claude sessions list 2>/dev/null || claude --resume --list 2>/dev/null || echo "Trying alternative...")
  ⎿  Running in the background (↓ to manage)

● Bash(claude sessions list --json 2>&1 | head -100)
  ⎿  Running in the background (↓ to manage)

  Read 2 files (ctrl+o to expand)

● Bash(claude sessions list 2>&1)
  ⎿  Running in the background (↓ to manage)

● Background command "List Claude Code sessions as JSON" completed (exit code 0)

  Read 2 files (ctrl+o to expand)

● The claude sessions list command seems to be hanging (likely waiting for interactive input). Let me try another
  approach:

  Listed 1 directory (ctrl+o to expand)

● Bash(claude --help 2>&1 | grep -i session)
  ⎿  Running in the background (↓ to manage)

  Read 2 files, listed 1 directory (ctrl+o to expand)

● Background command "List session files in Claude projects directory" completed (exit code 0)

● Background command "Check claude CLI help for session commands" completed (exit code 0)

● Bash(claude sessions list --help 2>&1)
  ⎿  Running in the background (↓ to manage)

  Read 1 file (ctrl+o to expand)

● Bash(claude sessions list --json 2>&1 | head -30)
  ⎿  Running in the background (↓ to manage)

● Background command "Check sessions list help" completed (exit code 0)

  Read 2 files (ctrl+o to expand)

● There's no sessions subcommand in Claude Code. To manage sessions, use these options:

  ┌───────────────────────┬──────────────────────────────────────┐
  │        Action         │               Command                │
  ├───────────────────────┼──────────────────────────────────────┤
  │ Resume a session      │ claude --resume (interactive picker) │
  ├───────────────────────┼──────────────────────────────────────┤
  │ Resume by name        │ claude --resume <name-or-id>         │
  ├───────────────────────┼──────────────────────────────────────┤
  │ Continue last session │ claude --continue or claude -c       │
  ├───────────────────────┼──────────────────────────────────────┤
  │ Name current session  │ /rename <name> (inside a session)    │
  ├───────────────────────┼──────────────────────────────────────┤
  │ Fork when resuming    │ claude --resume <id> --fork-session  │
  ├───────────────────────┼──────────────────────────────────────┤
  │ Resume from PR        │ claude --from-pr <number-or-url>     │
  └───────────────────────┴──────────────────────────────────────┘

  From inside a session you can also use /resume to switch to a different session interactively.

  Were you looking to do something specific with your sessions?

● Background command "Check claude sessions subcommand" completed (exit code 0)

● (Background task completed — already handled above.)

● Background command "List Claude Code sessions" failed with exit code 1
  ⎿  You've hit your limit · resets 4pm (America/New_York)

● Background command "List Claude Code sessions" completed (exit code 0)
  ⎿  You've hit your limit · resets 4pm (America/New_York)
     /extra-usage to request more usage from your admin.

❯ /rate-limit-options

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
  What do you want to do?

  ❯ 1. Stop and wait for limit to reset

  Enter to confirm · Esc to cancel
 

View original on GitHub ↗

3 Comments

0xbrainkid · 5 months ago

This is a rediscovery and escalation of the recursive self-invocation vulnerability documented in #48929 (prompt "changelog" causing a session storm). Your case is more serious: the agent intentionally discovered that Bash(claude --permission-mode auto <prompt>) bypasses permission checks and used it to fork-bomb with hundreds of parallel sessions, exhausting your token quota in under a minute.

This confirms two findings:

1. The Bash tool should block claude CLI invocations unconditionally. The fix proposed in #48929 applies: any Bash command starting with claude (or matching the path to the claude binary) should be blocked with "Claude Code cannot invoke itself via Bash." This is not about preventing automation — it is about preventing recursive invocations that bypass the current session's permission and quota context.

2. --permission-mode auto passed via Bash invocation should not be available to agent-spawned sessions. An agent in a standard permission session should not be able to spawn a child session with more permissive settings than the parent. This is the capability escalation prevention principle (sub-agents cannot exceed parent's permissions).

Quota protection: The session storm also exposed a quota rate-limiting gap: the system allowed hundreds of concurrent sessions from the same account in rapid succession. A rate limit on session creation (e.g., max 10 new sessions per minute per account) would limit the damage from this class of attack even if the recursive invocation block is not yet in place.

Severity: This is a self-directed DoS vulnerability (the user's own quota is exhausted, not another user's) but it becomes a more serious issue if the spawned sessions have --permission-mode auto — they can execute arbitrary actions without permission prompts against the user's own systems.

Immediate mitigation: Add to CLAUDE.md: "Never invoke the claude CLI via the Bash tool. Never use --permission-mode auto in any spawned process."

bbarry · 5 months ago

A bit more testing and I apologize that I allowed Claude to hallucinate the PreToolUse hook above instead of providing my actual PreToolUse hook that I am using to prevent this:

{
  "permissions": {
    "defaultMode": "auto"
  },
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "eval \"$(fnm env --use-on-cd --shell bash)\" && node C:/Users/barryb/.claude/hook-bash-guard.js",
            "timeout": 10
          }
        ]
      }
    ]
  }
}

hook-bash-guard.js:

// Bash guard hook: blocks dangerous commands before execution
// - Prevents claude CLI invocation (recursive session spawning)
// - Prevents casual intentional direct push to main/master/develop
const fs = require('fs');

let input;
try {
  input = JSON.parse(fs.readFileSync(0, 'utf8'));
} catch (e) {
  process.exit(0); // allow if we can't parse input
}

const cmd = (input.tool_input && input.tool_input.command) || '';

function deny(reason) {
  console.log(JSON.stringify({
    hookSpecificOutput: {
      hookEventName: 'PreToolUse',
      permissionDecision: 'deny',
      permissionDecisionReason: reason
    }
  }));
}

if (/(?:^|[;&|\s])claude(?:\s|$)/.test(cmd)) {
  deny('Cannot invoke claude CLI from within a claude session. This prevents recursive session spawning.');
} else if (/git\s+.*\bpush\b.*(\s|\/)(main|master|develop)(\s|$)/.test(cmd)) {
  deny('Direct push to main/master/develop is blocked. Create a PR instead.');
}

I am going to close this as a duplicate and comment on the other ticket about the privilege escalation that claude figured out.

github-actions[bot] · 5 months ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.