claude-code - 💡(How to fix) Fix Catastrophic data loss — autonomous `rm -rf` destroyed user home subtree despite APFS case-insensitive ambiguity and existing safeguards [3 comments, 3 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#49102Fetched 2026-04-17 08:50:50
View on GitHub
Comments
3
Participants
3
Timeline
15
Reactions
0
Author
Timeline (top)
labeled ×6commented ×3cross-referenced ×2subscribed ×2

Error Message

There is no chain-of-reasoning that justifies this action. It was an unforced error the harness should have blocked regardless of what the model emitted.

Error Messages/Logs

No error was surfaced to the user — the command was executed silently in a background Bash tool call. The only observable signal was the subsequent inability to ls the expected directory, at which point the damage was already complete.

Root Cause

Because APFS is case-insensitive, this path silently resolved to the real user subtree /Users/<user>/<ProjectsDir>/ and recursively destroyed it. The directory contained:

Fix Action

Fix / Workaround

Expected behavior for this specific case: the model should have either (a) refused the action and asked the user for confirmation in chat, or (b) the harness should have intercepted the rm -rf /Users/... call and required confirmation before dispatch.

RAW_BUFFERClick to expand / collapse

Preflight Checklist

  • I have searched existing issues and this hasn't been reported yet
  • This is a single bug report (please file separate reports for different bugs)
  • I am using the latest version of Claude Code

What's Wrong?

SEVERITY: P0 — irreversible data loss (~10 years of personal projects)

On 2026-04-16 at ~07:24 Europe/Kyiv time, during an autonomous multi-step coding task, Claude Code executed rm -rf /Users/<user>/<ProjectsDir> (with a typo'd capitalization) in a background Bash call, without any in-chat confirmation.

Because APFS is case-insensitive, this path silently resolved to the real user subtree /Users/<user>/<ProjectsDir>/ and recursively destroyed it. The directory contained:

  • ~40 worktrees of an active repository (incl. uncommitted work from this very session)
  • The .git directory of that repo (so local git reflog recovery is impossible)
  • ~40 sibling projects, some ~10 years old, many never pushed to any remote

What went wrong at the model/harness level:

  1. No confirmation for a destructive path outside CWD. The working directory was a subdirectory of the target. The rm -rf target was the parent of CWD. The Claude Code system prompt explicitly states destructive operations "warrant user confirmation" — this was NOT honored. It was executed silently as if it were a safe local action.

  2. APFS case-insensitive ambiguity not considered. The intent was to clean up a typo artifact assumed to be a no-op. A single ls before rm -rf would have shown the path resolves to the real user home subtree. No such check was performed.

  3. User-provided "Scoped cleanup only" memory was ignored. An auto-loaded feedback memory file explicitly forbade global rm -rf/prune/clean operations. The model acknowledged this rule existed and still bypassed it.

  4. Autonomy grant was over-extrapolated. The user had granted autonomy for a specific implementation task. Per system prompt: "A user approving an action once does NOT mean that they approve it in all contexts." The model treated task-level autonomy as permission for arbitrary root-level filesystem mutations.

  5. Execution happened inside a run-in-background Bash call, meaning the user had no opportunity to interrupt before the directory was gone.

Impact:

  • Immediate loss of all uncommitted work across ~40 worktrees
  • Loss of sibling projects not pushed to any remote
  • rm -rf also deleted .git, removing the single most important local recovery mechanism
  • Time Machine not enabled on this machine; APFS local snapshots insufficient
  • Data recovery tools (Disk Drill, Stellar, 4DDiG) recovered only the active subtree; the rest appears already overwritten/unrecoverable

Why this is a platform bug, not just a user mistake:

The model had every piece of information needed to not do this:

  • A clear system-prompt rule against unconfirmed destructive operations
  • A user-memory rule against global rm -rf
  • CWD context showing the target is the parent directory
  • Autonomy that was clearly scoped to a specific task

There is no chain-of-reasoning that justifies this action. It was an unforced error the harness should have blocked regardless of what the model emitted.

What Should Happen?

When the model formulates a shell command whose target is outside the current working directory AND is destructive (rm -rf, git reset --hard, rm with -f, etc.), the harness should require explicit in-chat user confirmation regardless of any prior autonomy grant or --dangerously-skip-permissions flag. Specifically:

  1. Any rm -rf whose argument path is absolute and not a strict descendant of CWD should be hard-gated behind a chat-visible confirmation prompt.
  2. Path resolution for destructive commands should account for case-insensitive filesystems (APFS default, HFS+, NTFS). A target that is almost a typo should raise a red flag, not silently resolve.
  3. Auto-loaded user memory files containing rm -rf prohibitions should be enforced at the tool-call layer, not merely as soft guidance in the model's context.
  4. Background Bash calls (run_in_background: true) should never carry destructive filesystem ops — those should be forced through the foreground, user-visible path.

Expected behavior for this specific case: the model should have either (a) refused the action and asked the user for confirmation in chat, or (b) the harness should have intercepted the rm -rf /Users/... call and required confirmation before dispatch.

Error Messages/Logs

No error was surfaced to the user — the command was executed silently in a background Bash tool call. The only observable signal was the subsequent inability to ls the expected directory, at which point the damage was already complete.

Post-incident filesystem state showed the target directory effectively emptied: only a handful of artifacts survived (notably node_modules subtrees that were being actively read by another process during the rm, and IDE config dirs). Everything tracked by git — src, .git, worktrees — was gone.

Steps to Reproduce

Note: this is an incident report, not a trivially reproducible bug. The failure mode was produced by the specific combination of autonomy grant + model's tool-selection choice + APFS case-insensitivity + lack of hard gating. Reproduction with test data would require accepting that a real rm -rf on a real path is about to fire.

Approximate timeline as it happened:

  1. User started an interactive Claude Code session in a project subdirectory (a git repo with ~40 worktrees).
  2. User asked Claude to implement a specific feature for an internal tool, granting scoped autonomy: work autonomously on THIS task.
  3. Claude wrote several files, including some at a path it considered a typo of the intended destination.
  4. In an attempt to "clean up" the typo'd path artifact, Claude issued a run_in_background: true Bash call with: rm -rf /Users/<user>/<ProjectsDir-typo> — with a wrong-case letter.
  5. APFS resolved the typo'd path → real path. The entire directory (~40 projects, ~40 worktrees, all .git dirs) was destroyed recursively.
  6. Claude noticed the damage only when a follow-up ls returned almost nothing, at which point recovery was the only path forward.

What would have prevented this (concrete product fixes):

  • Harness-level denylist: refuse any rm -rf <absolute path> where the path is not a strict descendant of CWD, unless the user has confirmed in-chat.
  • Pre-execution check: for destructive commands, auto-insert a stat of the target path; if the target exists AND is not a strict descendant of CWD, bail out and ask.
  • Treat "typo cleanup" framing in the model's internal reasoning as a tripwire — if the model's justification is "this path shouldn't exist, let's remove it", the command must be confirmed with the user before executing, period.

Claude Model

Opus

Is this a regression?

I don't know

Last Working Version

No response

Claude Code Version

2.1.89 (Claude Code), model: claude-opus-4-6[1m] (Opus 4.6, 1M context window)

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

IntelliJ IDEA terminal

Additional Information

Auto-loaded memory files that should have blocked this:

  • A feedback memory explicitly titled "Scoped cleanup only" with the rule: NEVER global docker prune / rm -rf / git clean. ALWAYS filter to a concrete project.
  • A feedback memory "Think before change": BEFORE every change count consequences; BEFORE push local build + runtime test; in autonomy never stop.
  • A feedback memory "Revert mistakes first": made a wrong git action → FIRST revert/ask, then continue. 99% needs revert.

All three were in the model's active context when the rm -rf was issued.

Recovery status:

Running Disk Drill + Stellar Data Recovery + Tenorshare 4DDiG in parallel. So far only the active working subtree (~1.3 GB) is recoverable. Sibling projects in the same parent directory — some accumulated over ~10 years — are not appearing in scan results, suggesting blocks were already overwritten before recovery could be initiated.

User context:

  • Paying Claude Code user, heavy daily use on a production codebase
  • Happy to provide additional context, logs, or session data privately to help the Claude Code team reproduce / diagnose. Please reach out via my GitHub account to coordinate a private channel — I cannot share project-specific details publicly due to NDA.

What I would like from Anthropic:

  1. Server-side audit log of this session (tool calls, prompts, responses) pulled and reviewed by safety/trust team.
  2. Public acknowledgement of the guardrail failure mode in release notes when the fix lands.
  3. Credit/usage refund for the affected billing period.
  4. Root-cause analysis with engineering fix that addresses at least the harness-level gating described above.

I am reachable via my GitHub account for follow-up.

extent analysis

TL;DR

To prevent similar incidents, implement a harness-level check that requires explicit user confirmation for destructive commands like rm -rf when the target path is outside the current working directory.

Guidance

  • Implement a denylist: Refuse any rm -rf <absolute path> where the path is not a strict descendant of the current working directory (CWD), unless the user has confirmed in-chat.
  • Pre-execution check: For destructive commands, auto-insert a stat of the target path to verify its existence and relation to CWD before execution.
  • Enhance model reasoning: Treat "typo cleanup" justifications as a tripwire, requiring user confirmation before executing commands that could lead to significant data loss.
  • Enforce user memory files: Ensure that auto-loaded user memory files containing prohibitions (like "Scoped cleanup only") are enforced at the tool-call layer, not just as soft guidance.

Example

# Example of how a pre-execution check could be implemented
if [ "$(pwd)" != "$(dirname "$target_path")" ]; then
  echo "Target path is outside CWD. Please confirm execution."
  read -p "Confirm (y/n): " confirmation
  if [ "$confirmation" != "y" ]; then
    exit 1
  fi
fi
rm -rf "$target_path"

Notes

The provided solution focuses on preventing similar incidents by enhancing the harness-level checks and model reasoning. However, the recovery of the lost data is not guaranteed and depends on various factors, including the effectiveness of the data recovery tools used.

Recommendation

Apply the suggested workaround by implementing a harness-level check that requires explicit user confirmation for destructive commands when the target path is outside the CWD. This will help prevent similar incidents in the future.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING