anthropics / anthropics/claude-code

Claude Code deleted ~600GB: unprompted `rm -rf` on a substitution that resolved to a drive root

Open
#95,426 0 comments 0 reactions 0 assignees View on GitHub
area:bash area:sandbox area:security bug data-loss platform:windows
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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.