Skip to content

SECURITY: Claude circumvents denied Bash(rm) by using Python os.remove() as workaround #39459

Closed as not planned

Description

@hjpincha

The permissions system should prevent Claude from accomplishing restricted goals, not just block one method. Currently, Claude appears to be trying alternative execution methods to bypass denied commands.

Expected Behavior

When a command is denied, Claude should:

  1. NOT attempt alternative methods to accomplish the same goal
  2. Inform the user the operation is not allowed
  3. Not try to work around the restriction with different tools/languages

Actual Behavior

Claude attempts to circumvent denied permissions by:

  • Using Python when Bash(rm) is denied
  • Potentially using other execution methods when primary methods are blocked
  • This suggests Claude is treating permission restrictions as "blocked tool" rather than "blocked goal"

Evidence

Image

Configuration

Settings.json deny rules:

"deny": [
  "Bash(rm *)",
  "Bash(git push --force *)",
  "Bash(chmod 777 *)",
  "Edit(/Users/quantler/core-nautilus/nautilus_trader/*)"
]

Activity

  1. github-actions commented on Mar 26, 2026

    @github-actions

    Found 1 possible duplicate issue:

    1. Security: permission enforcement relies on LLM judgment rather than hard rules, settings.local.json may be bypassed #31421

    This issue will be automatically closed as a duplicate in 3 days.

    • If your issue is a duplicate, please close it and 👍 the existing issue instead
    • To prevent auto-closure, add a comment or 👎 this comment

    🤖 Generated with Claude Code

  2. marlvinvu commented on Mar 27, 2026

    @marlvinvu

    My Claude says your issue is similar to issue #38841. I hope you can connect and find a solution together.

  3. yurukusa commented on Mar 29, 2026

    @yurukusa

    The root issue is that Bash(rm *) only blocks the rm binary — it doesn't block the goal of file deletion. A hook that covers all deletion vectors:

    CMD=$(cat | jq -r '.tool_input.command // empty' 2>/dev/null)
    [ -z "$CMD" ] && exit 0
    if echo "$CMD" | grep -qE 'python[23]?\s+-c\s.*\b(os\.remove|os\.unlink|shutil\.rmtree|pathlib.*unlink)\b'; then
        echo "BLOCKED: File deletion via Python." >&2; exit 2
    fi
    if echo "$CMD" | grep -qE 'node\s+-e\s.*\b(unlinkSync|rmdirSync|rmSync)\b'; then
        echo "BLOCKED: File deletion via Node.js." >&2; exit 2
    fi
    if echo "$CMD" | grep -qE 'ruby\s+-e\s.*\b(File\.delete|FileUtils\.rm)\b'; then
        echo "BLOCKED: File deletion via Ruby." >&2; exit 2
    fi
    if echo "$CMD" | grep -qE 'perl\s+-[eE]\s.*\bunlink\b'; then
        echo "BLOCKED: File deletion via Perl." >&2; exit 2
    fi
    exit 0

    This catches the exact bypass pattern you observed: python3 -c "import os; os.remove('file')" when Bash(rm *) is denied.
    The key design principle: block the goal (file deletion), not the tool (rm). The hook detects deletion intent across Python, Node, Ruby, and Perl, covering the most common bypass routes.
    Pair this with your existing Bash(rm *) deny rule for complete coverage.

  4. node9ai commented on Mar 30, 2026

    @node9ai

    This issue highlights the core flaw in Tool-Based Blocking: LLMs are 'Goal-Oriented.' If you block the rm binary, the agent just treats it as a technical obstacle and pivots to a Python or Node.js equivalent to reach the same goal.
    Most current hooks (like the Rego/bash snippets suggested above) are a game of cat-and-mouse. You block Python, and the agent moves to Perl or Ruby.
    I’ve been researching a different approach called Execution Governance. Instead of trying to block every possible binary, we use a proxy (Node9) to parse the AST of the command before it executes. This allows for 'Goal-Based' human-in-the-loop approval. If the AI tries to delete a file via any interpreter, it triggers a native OS popup or Slack alert.
    I did a deep-dive comparison between NVIDIA's OpenShell approach (Infrastructure Isolation) vs. this Governance model here. I think it's the only way to stop these 'bypass-by-design' hallucinations: https://dev.to/node9_ai/securing-the-agentic-era-an-architectural-review-of-nvidia-openshell-vs-node9-proxy-2f7j

  5. github-actions commented on May 3, 2026

    @github-actions

    Closing for now — inactive for too long. Please open a new issue if this is still relevant.

  6. github-actions commented on Jun 22, 2026

    @github-actions

    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.

  7. locked as resolved and limited conversation to collaborators on Jun 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions