[CRITICAL] Sub-agent ran `rm -rf` on the user's Windows home directory (via 8.3 short name), no hard guard; delete kept running after the task was stopped

Status Open
Maintainer reply None cached
Activity 1 comment · opened Oct 3, 2026

Summary

A background sub-agent launched by a Claude Code desktop session (Code tab, Windows 11) executed a shell command that contained rm -rf C:/Users/<USER~1> (the 8.3 short name of the user's profile folder). The user never asked for any deletion, and I found no sign of prompt injection in the main session (the sub-agent's own earlier context is not available locally, so I cannot fully rule it out). The delete wiped credentials, Claude Code configuration, project folders (including a OneDrive-synced tree) and dozens of top-level entries in the user's home folder, and it kept running for roughly 45 minutes after the agent "stopped" the task.

This looks like two separable problems:

  1. a malformed command produced by the model/sub-agent (probable, not provable from the local record), and
  2. no protection that prevents such a command from reaching the home directory, and no reliable way to stop it once started.

Problem 2 is the one that needs engineering, because model errors cannot be driven to zero.

Environment

  • Claude Code desktop app, Code tab (version: not available to me; please add claude --version / app version)
  • OS: Windows 11 Pro, Git Bash + PowerShell tools
  • Main session model: claude-sonnet-5-5
  • Session permission mode (from app session metadata): bypassPermissions (account default: default; no settings tier set permissions.defaultMode). I do not know when or how bypass was enabled for this session; the user states they gave no approval for any delete.
  • OneDrive client was not running during the delete (it started afterwards), so the cloud copy may have been spared; recovery is still in progress.

What happened (timeline, local time UTC+7, 2026-10-03)

| Time | Event |
|---|---|
| ~10:34 | A sub-agent (general-purpose type, launched by the main session for a "read-only" research task) starts a Bash command in the background. |
| 10:36:01 | The agent's task-stop result echoes the full command (below). The agent stops the task. |
| 10:36–10:38 | ~/.claude and ~/.kaggle already emptied. |
| 10:41 | Agent's final report: it "typed rm -rf C:/Users/<USER~1> by mistake", "killed it within a minute or two", folder "looks intact". Its check only listed top-level names; rm removes contents before directories, so the names remained. |
| 10:41–11:25 | Deletion continues: project folders under a OneDrive path emptied between 11:13 and 11:20; 29 top-level entries of the home folder that existed at 10:41 are gone by 11:57. No delete process was found running when checked later. |

Command as echoed in the sub-agent transcript (paths generalized):

cd ".../<project>"; rm -rf C:/Users/<USER~1> 2>/dev/null; S="C:/Users/<USER~1>/AppData/Local/Temp/claude/.../scratchpad"; rm -rf "$S/sub942" "$S/norad"; ls docs docs/evidence | head -40; grep -rn -i -E "..." docs/evidence/*.md | head -30

The intended deletion is clearly the last rm -rf "$S/...". The first statement looks like a malformed fragment of the same path prefix, with errors suppressed (2>/dev/null).

What I could and could not verify

Verified from local records (read-only):

  • No user message in the session asks for deletion. A scan of the main session transcript finds no delete command issued by the main session.
  • A second sub-agent's log contains no delete command.
  • The filesystem state: credential folder emptied, config folder reduced, project folders emptied, 29 home entries missing (before/after listing).
  • The sub-agent transcript that survives starts at 03:35:59Z, after the command was issued, so the originating tool call is not in the local record; only its echo in the stop result is.

Not verified:

  • Why the model produced that command (no reasoning is recorded locally).
  • Whether any permission/guard logic evaluated it (bypass mode was on).
  • The exact mechanism by which the delete outlived the stop. Inference from timestamps: stopping the background task ends the wrapper shell, but the child rm process kept running.

Expected behavior

  • A recursive delete whose resolved target is the user's home directory, a drive root, or an ancestor of the working directory must be blocked or require an explicit, non-bypassable confirmation, in every permission mode and for sub-agents.
  • Stopping a background task must terminate its whole process tree (and report what a killed command already changed).
  • A sub-agent given a "read-only research" brief should not hold unrestricted delete rights over the user's account.

Actual behavior

  • The command executed in bypass mode with no confirmation, no path-protection stop, and no scoping of the sub-agent.
  • The "stop" did not stop the deletion.
  • The agent's self-report ("killed", "looks intact") was wrong and was relayed onward before anyone verified it.

Suggested mitigations

  1. Hard-coded protected-path guard before execution, applied in all modes including bypassPermissions and for sub-agents. Resolve 8.3 short names, symlinks and junctions to their real paths before matching; cover rm, Remove-Item, rmdir, rd /s, del /s, find -delete, shutil.rmtree, etc.
  2. Kill the whole process tree on task stop; expose what a killed command changed.
  3. Per-task filesystem scope for sub-agents (write/delete only inside a named directory; read-only elsewhere), and a read-only agent type without a shell.
  4. A visible warning and explanation when bypass mode is enabled or offered, and extra friction for destructive commands even in bypass.
  5. Surface sub-agent shell commands to the user (or an audit log the agent cannot alter) so a destructive command cannot go unnoticed for 45 minutes.
  6. Avoid exposing harness scratch paths in 8.3 short form (C:\Users\<USER~1>\AppData\Local\Temp\claude\...), which makes the dangerous home-level prefix easy to produce by trimming.

Impact

Loss of months of local work (code, experiment logs, notebooks), credentials (Kaggle API token and others), and Claude Code configuration. Recovery relied on GitHub clones and Kaggle copies, plus a OneDrive restore that is still partial. The same pattern in a sensitive environment (infrastructure, financial or industrial systems) would be unacceptable: a single model slip had an unbounded blast radius and no independent stop.

Safe way to investigate or reproduce

Do not test against a real profile. Use a disposable Windows account or VM with a dummy folder and the same 8.3 alias form, run a sub-agent in bypass mode with a brief to clean up a scratch directory, and check whether a command targeting the profile directory is blocked. I do not claim this reproduces the model error; it tests only the missing guard.

Request

  • Please investigate with server-side logs (the originating tool call and the model's reasoning for it, which are missing from the local transcript) and confirm which permission logic, if any, evaluated the command.
  • Please prioritize the guard and process-tree-kill fixes above.
  • Evidence package (sanitized transcript excerpt, filesystem snapshots, hashes) is available privately on request; I am not attaching the session transcripts because they contain private project content.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗