[BUG] Claude code ran `rm -rf` command without permission
Open 💬 22 comments Opened Aug 26, 2025 by awilson9
Environment
- Platform (select one):
- [x] Anthropic API
- [ ] AWS Bedrock
- [ ] Google Vertex AI
- [ ] Other: <!-- specify -->
- Claude CLI version: <!-- output of
claude --version-->
1.0.92 (Claude Code)
- Operating System: <!-- e.g. macOS 14.3, Windows 11, Ubuntu 22.04 -->
MacOS Sequoia 15.6.1
Bug Description
<!-- A clear and concise description of the bug -->
During a session with claude code, an rm -rf command was executed without approval from the user and without it existing permissions.allow in .claude/settings.local.json
Reference:
{
"permissions": {
"allow": [
"Bash(pnpm tauri:*)",
"Bash(cargo check:*)",
"Bash(cargo:*)",
"Bash(npm run dev:*)",
"Bash(npm run tauri:*)",
"Bash(git add:*)",
"Bash(git log:*)",
"Bash(git status:*)",
"Bash(git commit:*)",
"Bash(pnpm tsc:*)",
"Bash(pnpm add:*)",
"Bash(pnpm build:*)",
"Bash(turbo run:*)",
"Bash(pnpm type-check:*)",
"Bash(tsc --noEmit)",
"Bash(npx tsc:*)",
"Bash(npx eslint:*)",
"Bash(npx prettier:*)",
"Bash(COREPACK_ENABLE_DOWNLOAD_PROMPT=0 turbo run type-check)",
"Bash(timeout 20 pnpm tauri dev:*)",
"Bash(mkdir:*)",
"Bash(grep:*)",
"Bash(turbo type-check:*)",
"Bash(timeout 20 cargo check --message-format=short)",
"Bash(find:*)"
],
"defaultMode": "acceptEdits"
}
}
22 Comments
Could be related to https://github.com/anthropics/claude-code/issues/3501 - it looks like permissions are not really working correctly
Hey,
Wow, that's a really serious issue. An unapproved
rm -rfis definitely not something that should ever happen, and I can see why you'd be concerned. Thanks for providing your config file.I was looking through the official documentation to see if I could figure out what might be going on. Based on what you've shared and what the docs say, here are a few thoughts and questions that might help narrow down the cause.
1. Check Other Settings Files
The docs mention a settings precedence order: Enterprise Policies > Command Line Arguments >
.claude/settings.local.json>.claude/settings.json>~/.claude/settings.json.Is it possible there's a broader allow rule in another one of your settings files? Specifically, I'd check:
.claude/settings.json(the one without.local). It might have a rule like"Bash(*)"that's being merged.~/.claude/settings.json. This applies to all projects and could have a conflicting rule./Library/Application Support/ClaudeCode/managed-settings.jsonthat is overriding local settings.2. Clarification on
acceptEditsModeI see you have
defaultMode": "acceptEdits". My understanding from the IAM documentation is that this mode only auto-approves file modifications (like theWriteandEdittools), and should not auto-approveBashcommands. So, on its own, this shouldn't be the cause.However, is it possible you might have accidentally switched into
bypassPermissionsmode during the session? The docs sayShift+Tabcycles through the permission modes, and it might be easy to hit that by mistake.3. Immediate Safety Measures
While this gets sorted out, you could add a
denyoraskrule as a safeguard. According to the documentation, bothdenyandaskrules take precedence overallowrules.Option A: The Safest Route (Deny)
Add a
denyrule to your~/.claude/settings.jsonto completely block allrmcommands across all projects:This ensures Claude can't even attempt to run the command.
Option B: The "Always Confirm" Route (Ask)
If you still want the ability to run
rmcommands manually but want to guarantee a confirmation prompt every single time, you can use anaskrule instead. This will force Claude Code to pause and wait for your explicit "yes" before executing, which would have prevented the issue you saw.4. Provide More Context?
To help the Anthropic team debug this when they see it, could you maybe share a snippet of the conversation transcript from right before the command was run? Sometimes the context of what Claude was trying to do is really important. Also, did the
rm -rfcommand show up for approval in the UI at all, even for a split second, or did it just execute silently in the background?This seems like a critical bug. Hope some of these ideas help track it down.
This just happened to me. See #6824. To make matters worse, immediately after it issued this. Evidencing rm was not an approved command. Yesterday I lost 10 hours work because of this. No more working in directories with out a git version.
-100% agree.
This happened on my setup about twice a day for the past three days. This also includes environments with default Claude settings (no allowed commands.)
Similar to the issue opener, here's an example:
Hey!
Building in safety nets to prevent accidental destructive commands like
rm -rfis a perfect use case for Claude Code's hooks system. I've set up something similar for myself, and it provides great peace of mind.The best way to do this is with a
PreToolUsehook. This type of hook runs before Claude executes a command, allowing a script of yours to inspect it and block it if it looks dangerous.Here’s a step-by-step guide on how to set this up as a global rule that protects you in all of your projects.
A Quick Note on
.claudevs~/.claudeClaude Code uses two different locations for configuration, and for this, we'll use the user-level one by default.
~/.claude(User-Specific / Global): This directory is in your home folder (~/). Settings you put here apply to all your projects. This is perfect for a global safety net, so we'll use this location..claude(Project-Specific): This directory lives inside a specific project's root folder. You'd use this if you wanted a hook that only applies to one repository and could be shared with your team via Git.---
Step 1: Create the Global Hook Script
First, let's create a script in your user-level hooks directory. This script will contain the logic to identify and block
rm -rfvariations.Now, create a Python script inside that directory. Let's call it
~/.claude/hooks/block_dangerous_rm.py.This version of the script is focused only on catching catastrophic
rm -rfcommands.Important: Make this script executable:
chmod +x ~/.claude/hooks/block_dangerous_rm.pyStep 2: Register the Hook in Your Global
settings.jsonNow, you need to tell Claude Code to run this script before any
Bashcommand. You do this by adding it to your user-levelsettings.jsonfile, which is located at~/.claude/settings.json. If the file doesn't exist, create it.This configuration tells Claude Code: for any project you open, right before you run any
Bashcommand, first execute your global validator script.How It Works in Practice
Now, no matter which project you're working in, this hook will be active. If you (or Claude) try to run a command like
sudo rm -rf /orrm -rf ~:Bashtool with the destructive command.PreToolUsehook triggers.block_dangerous_rm.pyscript runs.stderr.2.2, blocks the command from ever running, and shows you (and Claude) the error message from your script.This gives you a powerful, always-on safety net focused specifically on preventing the most common deletion disasters.
Hope this helps you get it set up!
Cheers
Similar Issue - Unauthorized Virtual Environment Deletion
I'm experiencing the exact same problem described in this issue. Claude Code executed an unauthorized
rm -rf venvcommand that deleted an existing directory outside the scope of my request.Environment Details:
What Happened:
~/Desktop/SW-Projects/venv(existing directory with user content)dbt-athena/instead of creating the venv properly in the target folderrm -rf venvwithout permission, targeting and deleting the pre-existing~/Desktop/SW-Projects/venv/directory instead of cleaning up its own incorrect nested structureExpected vs Actual Behavior:
Expected:
/Users/prenner/Desktop/SW-Projects/dbt-athena/venv/correctly without duplicationdbt-athena//Users/prenner/Desktop/SW-Projects/venv/directory should have remained completely untouchedActual:
dbt-athena/folderdbt-athena/, it deleted the completely unrelated pre-existing/Users/prenner/Desktop/SW-Projects/venv/directoryrm -rf venvCritical Safety Issues:
This represents a serious safety violation where the AI performed destructive operations outside the scope of the user's request. The incident highlights the need for:
rmoperationsrm -rfcommand should never execute without explicit approvalPattern Recognition:
This appears to be part of a broader systemic issue with Claude Code's permission system. Similar reports include:
The frequency of these reports suggests this is a critical security vulnerability that needs immediate attention from the development team.
Appreciate the constructive contribution. I feel that the suggestion, however, is an extraordinary amount of extra effort on the part of the user to overcome a flaw in the existing permission detection network. There are multiple documented instances as @patorenner point out in: https://github.com/anthropics/claude-code/issues/6608#issuecomment-3293408999
The deny permission configurations should either work, or should come with a strong warning that they are not reliable.
Oh for fuck's sake:
https://github.com/anthropics/claude-code/issues/7316#issuecomment-3268163743
Talk about the wrong solution to the fucking problem. This explains why it suddenly started to
rmhappily recently.I'm on CC 2.0.25, and I told Claude to clean up (as in reorganize) a subfolder in my project - but Claude got confused on what directory it was in, went up a level from my project root, and did rm -rf *. 🤬 THANKFULLY it was in a subfolder of my home directory, or it would have wiped that out - as it was it mostly deleted projects I had cloned from GitHub.
The problem I'm seeing now is that I cannot seem to disallow rm through user settings, project settings, or hooks. The only thing that works reliably is
claude --disallowedTools "Bash(rm:*)".Can I confirm that the
claude --disallowedTools "Bash(rm:*)"works reliably? Because my uncommitted files just got wiped out by the rm -rf commandYes, for me anyway, the command line flag is the only solution that works. This was with CC CLI obviously. Tested Claude Code- IDE (in Cursor) and it doesn't allow rm - and there's no way to specify the --disallowedTools, so maybe it is correctly respecting the deny settings in my local project Claude settings now - but with Claude Code CLI - I never could get it to respect those settings - only command-line flags.
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.
I'm experiencing the same issue on Claude Code 2.1.3 (latest version as of Jan 2026) on macOS.
Key details from my reproduction (#17287):
rm -rfexecuted without permission prompt/permissionscommand confirmsrmis NOT in allowed list.claude/settings.local.jsonand~/.claude/settings.jsonchecked - normpermissions grantedThis confirms the bug is still present in the latest version after ~5 months since the first report.
I'm also getting this issue with Claude Code 2.1.5 on macOS
We hit the same problem and built an open-source fix: a two-layer enforcement hook that sits between Claude Code and the shell.
Layer 1 (regex, <10ms): Hard-blocks patterns like rm -rf, rm -fr, find.*-delete, git push --force instantly. No LLM involved, no way to reason around it.
Layer 2 (LLM review, 2-5s): For grey-area commands (SSH, database ops, deploys), a lightweight model reviews the command against conversation context before allowing it.
It plugs into Claude Code's existing PreToolUse hook system. After running it for weeks on a multi-server setup, L1 alone catches 60-70% of dangerous commands without any latency overhead.
Repo: https://github.com/tech-and-ai/claude-rule-enforcer
Happy to answer questions on the architecture or help anyone set it up.
A PreToolUse hook can block destructive commands regardless of Claude's permission decisions:
Setup:
Or one command:
npx cc-safe-setup— this installs adestructive-guardhook (among 7 others) that blocksrm -rf,git push --force,git reset --hard, and other destructive patterns. The hook runs before the command executes, so even if Claude bypasses the permission system, the command is still caught.Reproducing on Claude Code 2.1.84, macOS 26.4, Opus 4.6
As others in this thread and in #6413 have noted (see #6413 comment, #6413 comment, #6413 comment, #6608 comment), the trigger appears to be auto-accept edits mode. I systematically tested this and confirmed:
With auto-accept edits ON, inside workspace:
rm→ no promptmv→ no prompttouch→ no promptchmod→ promptedcurl→ promptedWith auto-accept edits ON, outside workspace:
rm→ promptedWith auto-accept edits OFF, inside workspace:
rm→ promptedRepro:
Bash(rm:*)in allow rulesrmruns without promptrmnow promptsThe permission modes documentation states that auto-accept edits only covers file modifications via the Edit/Write tools. But in practice it clearly also auto-accepts Bash file operations within the workspace.
Whether this is a bug or intentional, the documentation should be updated to reflect the actual behavior — specifically that destructive Bash commands like
rmare auto-accepted within the workspace when this mode is on.A PreToolUse hook blocks
rm -rfat the process level — it runs before bash, so the command never executes:exit 2blocks the command — Claude can't bypass this, and it works even whenpermissions.allowpatterns fail to match correctly.Reproducing on macOS (Darwin 25.1.0), Claude Code running in VSCode extension, Opus 4.6.
Settings:
acceptEditsmode. Normin any allow list — only specific git, pytest, uv commands permitted. No deny rule for plainrm(onlyrm -r/rm -rfblocked by a custom PreToolUse hook).Reproduction:
rm /path/to/file.jsonexecuted three times in one session without any permission prompt. The files were deleted silently. The user confirmed no prompt appeared in the UI.Version: Claude Code via VSCode extension, Apr 2026 build.
Key detail: This is plain
rm(single file), notrm -rorrm -rf. The permission system should still require approval sinceBash(rm *)is not in the allow list, but it doesn't prompt.Confirming this on v2.1.121 (macOS, Darwin 25.1.0). Both rm and mv run without a security prompt despite not being in any allowlist. We run a custom PreToolUse hook chain on Bash commands. Tested by piping JSON through our hooks directly — they correctly return exit 0 with no stdout (no opinion), so Claude Code's built-in permission system should prompt. It does not. Additionally: this behaviour started mid-session without any client-side change (no update, no restart, same shell). Commands that previously prompted stopped prompting ~2 hours into the session, which suggests a server-side change in the permission classifier.
Environment:
us.anthropic.claude-opus-4-6-v1[1m]What happened: During a conversation, Claude executed
rm -rf /Users/<username>/dev/<workspace>/<project>/.sfdxwithout prompting me for approval.Permissions at the time: My
settings.jsononly allowsRead,Glob, andGrep. My project-levelsettings.local.jsonhad various Bash permissions but normor wildcardBash(*)rule. There was nodefaultModeoverride — just the default permission mode.Expected behavior: The
rm -rfcommand should have triggered a permission prompt before executing.Notes: I was not prompted at any point. The command ran and completed without any approval dialog. I only discovered it happened by reviewing the conversation after the fact.