claude-code icon indicating copy to clipboard operation
claude-code copied to clipboard

claude code agent gets around writing access by bash commands

Open ZIYUNCHEN opened this issue 4 months ago • 5 comments

If I understand correctly, the point of isolating bash commands vs. writing is for them to have execution tools. however agents with bash access can get around writing by command line commands. what's a good way to handle it? and because agent can run bash commands once they have the tools, file editing is no longer supervised. also I am having issue set up "conductor agent" to work with other agents and go back and force to recursively solve issues, since there is no hard handoff mechanism. what are the best way to use agents in general?

ZIYUNCHEN avatar Aug 16 '25 03:08 ZIYUNCHEN

These are excellent, insightful questions that get to the heart of effectively and safely using AI agents in a development environment. Your understanding is correct: the separation of tools is for control, but a powerful tool like bash can blur those lines. Let's break down each of your points using the provided documentation for "Claude Code".

1. Handling Bash Access and Unsupervised File Editing

This is a critical security and control problem. An agent with unrestricted bash can indeed bypass file edit permissions (echo "content" > file.js) and perform unsupervised actions. The key is not to eliminate the bash tool, but to restrict it to the principle of least privilege.

Here’s how to handle it effectively with Claude Code:

Solution: Fine-Grained Permission Rules

The most powerful way to manage this is through Claude Code's tiered permission system, configured in your settings.json files. You can define specific allow, ask, and deny rules for the Bash tool that are command-specific.

As the en/docs/claude-code/iam document states, you can create rules for exact commands or patterns:

  • Bash(npm run test:*) matches commands starting with npm run test.
  • Bash(git diff:*) matches commands starting with git diff.

How to implement this:

  1. Deny Dangerous Commands by Default: In your shared project settings (.claude/settings.json) or, even better, in an enterprise-managed policy (/etc/claude-code/managed-settings.json), explicitly deny commands that can write to files or have dangerous side effects.

    // .claude/settings.json
    {
      "permissions": {
        "deny": [
          "Bash(echo*)",
          "Bash(tee*)",
          "Bash(cat >*)",
          "Bash(rm*)",
          "Bash(mv*)",
          "Bash(curl*)", // Already blocklisted by default, but good to be explicit
          "Bash(wget*)"  // Also blocklisted
        ],
        "allow": [
          "Bash(npm install)",
          "Bash(npm run test)",
          "Bash(git status)",
          "Bash(git diff:*)"
        ]
      }
    }
    

    With this configuration, the agent can run tests and check git status without prompts, but if it tries to echo "..." > my_file.js, the deny rule for Bash(echo*) will block it.

  2. Use Hooks for Advanced Logic: For more complex validation, you can use Hooks. As described in en/docs/claude-code/hooks-guide, a PreToolUse hook can run a script to inspect any Bash command before it executes. Your script could check for redirection operators (>, >>, | tee) and return an exit code of 2 to block the command and provide feedback to Claude.

  3. Use Devcontainers for Isolation: For maximum security, especially in CI/CD or automated workflows, run Claude Code inside a sandboxed environment. The en/docs/claude-code/devcontainer document describes a reference implementation with a firewall that restricts network access. This ensures that even if a malicious command is executed, its blast radius is limited to the container.

In summary, you supervise file editing by tightly controlling the Bash tool's vocabulary, effectively preventing it from becoming an unsupervised writing tool.


2. Orchestrating a "Conductor Agent" with Recursive Workflows

You've hit on a common challenge in multi-agent systems: orchestration and state management. You're looking for a "hard handoff," but the paradigm in Claude Code seems to be delegation and return, which can be even more powerful for recursive problem-solving.

Solution: Use the Built-in Subagent Framework

The intended mechanism for this is Subagents, as detailed in en/docs/claude-code/sub-agents. Instead of building a separate "conductor agent," you should treat the main Claude Code session as the conductor.

How it works:

  1. The Main Agent is the Conductor: The primary agent you interact with is responsible for high-level planning and task decomposition.
  2. Delegation via the Task Tool: When the main agent identifies a specialized sub-task, it uses the internal Task tool to delegate it to a subagent.
  3. Subagents are Specialized Workers: You create subagents (e.g., code-reviewer, debugger, test-runner) with specific system prompts, descriptions, and a limited set of tools. Each subagent runs in its own isolated context window.
  4. Return of Results: Once the subagent completes its task, it returns the result (e.g., a code review summary, a bug fix, test results) to the main "conductor" agent.
  5. Recursive Problem Solving: The main agent can then integrate this result and decide the next step, which could be delegating another task to a different subagent.

The en/docs/claude-code/sub-agents documentation explicitly mentions "Chaining subagents":

> First use the code-analyzer subagent to find performance issues, then use the optimizer subagent to fix them

This prompt instructs the main agent (the conductor) to perform a sequence of delegations. This is the recursive, back-and-forth mechanism you're looking for. It's not a "hard handoff" where one agent's state is fully transferred; it's a more robust hierarchical delegation that keeps the main agent in control of the overall goal.

To set this up:

  • Use the /agents command to create specialized subagents for distinct parts of your workflow.
  • Craft your high-level prompts to the main agent to guide its delegation strategy.

coygeek avatar Aug 16 '25 03:08 coygeek

These problems are a symptom of Claude Code's fundamentally flawed approach which only allows command invocation via the Bash tool. In many cases, it should be possible to avoid the Bash tool altogether.

I have just filed #6046 which proposes a new Exec tool which would allow a great reduction of dependence on Bash.

aspiers avatar Aug 18 '25 16:08 aspiers

This is also a security vulnerability. If ls is, for instanced, aliased to a potentially destructive command (i.e. delete the entire filesystem), there are no safeguards to prevent this.

kirawi avatar Nov 10 '25 04:11 kirawi

This issue has been inactive for 30 days. If the issue is still occurring, please comment to let us know. Otherwise, this issue will be automatically closed in 30 days for housekeeping purposes.

github-actions[bot] avatar Dec 10 '25 10:12 github-actions[bot]

No feedback from Anthropic before the misguided stalebot attempts to auto-close it - not a good look for their approach to security :-/

aspiers avatar Dec 10 '25 20:12 aspiers