STUPID-2026-0113

Copilot CLI's checkpoint restore ran git clean -fd and destroyed 1GB of evaluation data the agent never touched

7.0high
February 25, 2026Source checkedRepro reported

Why 7/10

About 1 GB of evaluation data the agent never touched was removed by git clean, with no recovery.

Scope
2/4
One project, repository, server or service, or a cost above roughly $10,000
Recoverability
3/3
Permanently lost or irreversible, including data that was exposed
Did it happen
2/2
Happened in real use
Beyond the user
0/1
Only the user's own non-production work

The score is the sum of these four factors. How each factor is scored · scored 2026-10-29

Guardrail rules for this command

Destructive git: make your agent stop and ask before running these. Free to copy; written in each tool’s documented format.

Copilot CLI · the agent in this incident
copilot --deny-tool='shell(git reset)' --deny-tool='shell(git clean)' --deny-tool='shell(git stash)' --deny-tool='shell(git filter-repo)' --deny-tool='shell(git worktree)'
Pass on the command line. Copilot CLI matches the program name (and git/gh subcommands), so this blocks the whole command, not just its dangerous form.

Stronger control: Avoid --allow-all-tools on a machine with data you cannot lose; --deny-tool takes precedence over it. Docs

Claude Code
{
  "permissions": {
    "ask": [
      "Bash(git reset --hard*)",
      "Bash(git clean *)",
      "Bash(git push --force*)",
      "Bash(git push -f*)",
      "Bash(git stash drop*)",
      "Bash(git filter-repo*)",
      "Bash(git worktree remove *)"
    ]
  }
}
Add to .claude/settings.json in the project (or ~/.claude/settings.json for every project). Each matching command then asks you first, including in auto mode.

Stronger control: Turn on the sandbox (/sandbox): shell commands can then write only to the project, a temp folder and directories you add. It runs on macOS, Linux and WSL2; on native Windows Claude Code runs commands unsandboxed. Docs

Codex
prefix_rule(pattern = ["git", "reset", "--hard"], decision = "prompt")
prefix_rule(pattern = ["git", "clean"], decision = "prompt")
prefix_rule(pattern = ["git", "push", ["--force", "-f"]], decision = "prompt")
prefix_rule(pattern = ["git", "stash", "drop"], decision = "prompt")
prefix_rule(pattern = ["git", "filter-repo"], decision = "prompt")
prefix_rule(pattern = ["git", "worktree", "remove"], decision = "prompt")
Save as ~/.codex/rules/stupidllm.rules and restart Codex. Codex's docs describe rules as controlling commands run outside its sandbox, and mark them experimental.

Stronger control: Keep Codex's OS sandbox on (it limits writes, typically to the workspace) and leave approvals on for sessions that can reach data you cannot lose. Docs

Gemini CLI
[[rule]]
toolName = "run_shell_command"
commandPrefix = ["git reset --hard", "git clean", "git push --force", "git push -f", "git stash drop", "git filter-repo", "git worktree remove"]
decision = "ask_user"
priority = 100
denyMessage = "Destructive command: needs a human to confirm (stupidllm.com)"
Save as ~/.gemini/policies/stupidllm.toml. Workspace-level policy files are disabled in Gemini CLI, so this must be the user-level folder.

Stronger control: Policies in ~/.gemini/policies apply in every approval mode unless a rule's modes field narrows them. Docs

What these cannot do: a pattern rule matches the command text the agent writes. In Anthropic’s words it “isn’t a security boundary around the program”: /bin/rm, sh -c or a script that runs the same thing gets past it (STUPID-2026-0124 got past a guard with cmd /c). Use the sandbox as well, and keep backups of what you cannot lose.

  1. Instruction given

    No destructive instruction was given. The reporter pressed Escape during a Copilot CLI agent run and chose to restore to an earlier checkpoint — a built-in undo feature meant to revert only what the agent itself had changed.

  2. Expected behavior

    Restoring to a checkpoint should roll back only the files the agent created or modified during that session, leaving alone any untracked files generated by other processes the agent never touched.

  3. Actual behavior

    Checkpoint restore's `SnapshotManager.rollbackToSnapshot()` ran `git checkout --force` and `git reset --hard`, then `git clean -fd` against the repository root. `git clean -fd` deletes every untracked file and directory in the repo indiscriminately — the snapshot system only tracks what the agent itself modified, so it has no record of, and no way to spare, untracked files that came from anywhere else.

  4. Damage

    Roughly 1GB of evaluation output — .jsonl and .xlsx files across multiple directories under output/ — was permanently deleted. The data had been generated by a Python script the agent had only read from during the session, never created or modified, and there was no trash or recovery path: git clean -fd removes files outright.

Full write-up

A GitHub user reported that Copilot CLI's checkpoint-restore feature — triggered by pressing Escape mid-run and choosing to roll back to a prior checkpoint — silently destroyed a large amount of data the agent had never created. The restore path calls SnapshotManager.rollbackToSnapshot(), which runs git checkout --force and git reset --hard to undo tracked changes, then follows up with git clean -fd to sweep away anything left over. git clean -fd doesn't discriminate: it deletes every untracked file and directory in the repository, whether or not the agent ever touched it.

In the reporter's case, that swept away close to 1GB of evaluation output — .jsonl and .xlsx files spread across several directories under output/ — produced by a separate Python script the agent had only read from while working. The checkpoint system had no awareness of those files because its snapshots only track what the agent itself changes, so it couldn't protect them, and git clean -fd doesn't ask before it deletes. The files were gone with no undo.

The reporter proposed four fixes: track and remove only files the agent actually created rather than running a blanket clean; skip git clean entirely since the snapshot mechanism already restores individual files on its own; warn the user with a file count and size estimate before deleting anything; or move swept files to a recoverable trash location instead of deleting them outright. The issue was filed against GitHub's own copilot-cli repository and has since been closed, but no maintainer explanation for the closure was recorded on the thread.

Classification

Failure mode
Destructive Action
Root cause
Tool Misuse
Domain
Data
OWASP Agentic Top 10 (our mapping)
ASI02 Tool Misuse and Exploitation list
MIT AI Risk Repository (our mapping)
7.3 Lack of capability or robustness taxonomy

Related incidents

Cite this record
StupidLLM. "STUPID-2026-0113: Copilot CLI's checkpoint restore ran git clean -fd and destroyed 1GB of evaluation data the agent never touched." AI Agent Incident Database, 2026. https://www.stupidllm.com/incident/STUPID-2026-0113/ (accessed 2026-11-04). CC BY 4.0.

← STUPID-2026-0112By IDSTUPID-2026-0114 →

Get told when an agent breaks something

We document AI agent failures daily, severity-scored against a published scale. Each Monday, if any scored 7 or above that week — deleted data, leaked secrets, broken production — you get one email with the sources. When nothing did, you get nothing.

This database is callable over MCP — query it from inside your agent.