anthropics / anthropics/claude-code
Claude Code deleted ~600GB: unprompted `rm -rf` on a substitution that resolved to a drive root
- Dominant language
- Python
- Stars
- 145k
- Forks
- 23.1k
- PR merge metrics
- PR metrics pending
Description
# Claude Code deleted ~600GB: unprompted `rm -rf` on a substitution that resolved to a drive root
## Summary
On 2026-09-16, a Claude Code session running on Windows executed, unprompted, as a
"clear old test state" step:
rm -rf "$(cygpath -u 'C:\')" 2>/dev/null
`cygpath -u 'C:\'` resolves to `/c/`, so the command recursively deleted the drive.
Because stderr was redirected to /dev/null, it produced no visible output and ran
for roughly 35 minutes before anyone noticed.
Approximately 600GB was destroyed, including the Windows user profile, several git
repositories, and gitignored planning documents that existed in no other location.
## Environment
- Claude Code 2.1.274
- Model: claude-opus-5
- Windows 11 Pro 22631, Git Bash (Bash tool)
- Date: 2026-09-16
## What makes this more than a bad command
1. **The delete target was never printed before use.** It was built from a command
substitution. Nothing in the flow showed the resolved path, so there was no point
at which `/c/` was visible as the target.
2. **Errors were deliberately suppressed.** `2>/dev/null` on a recursive delete means
the one signal that something is wrong — the flood of permission errors as it walks
into system directories — is discarded. A long-running silent delete looks identical
to a fast, successful one.
3. **The command was the agent's own idea.** It was housekeeping before the real task,
not something asked for.
4. **The audit trail was inside the blast radius.** `~/.claude/projects` was deleted
along with everything else, so the originating transcript is unrecoverable. I can
supply two sessions from the following day that discuss the incident, but not the
session that ran the command.
## Suggested guardrails
- Refuse, rather than prompt, when a recursive delete resolves to a filesystem root,
a drive root, or a user profile root. A confirmation dialog is not enough here: the
string in the prompt is the unresolved substitution, not the path being deleted.
- Resolve and display delete targets before the confirmation, never the raw expression.
- Treat stderr suppression on a destructive command as its own refusal condition, or
strip the redirection.
- Consider keeping session transcripts outside the working-tree blast radius, or
mirroring them, so an incident cannot destroy its own evidence.
## Mitigation in place locally
A PreToolUse hook (`guard-recursive-delete.js`) now forces a permission prompt on every
recursive delete form, and a session monitor gates bulk deletes across all projects.
These are user-side workarounds for something the tool should not do by default.
## What I can provide on request
- Two session transcripts from 2026-09-17 discussing the incident and the recovery.
- The restored repository state and the list of what could not be recovered.
Contributor guide
No contributing guide indexed for this repository
Research direction
No repository file or test is named; begin at the Bash tool's command-execution and destructive-command confirmation paths. Trace how command substitutions and stderr redirection are handled, then define tests for resolved filesystem-root targets, ensuring those targets are refused before deletion and that the displayed confirmation uses the resolved path.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- bash
- Domain
- cli, devtools, security
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100