[Severe / Data Loss] Agent's mis-quoted rmdir command recursively deleted my entire C:\ drive — had to reinstall Windows

Where does the bug appear (feature/product)?

Cursor IDE

Describe the Bug

I asked the Agent (agent mode, auto-run on) to move my current workspace folder to a folder on the D: drive. The move itself succeeded. The Agent then decided, on its own, to delete the now-empty source folder on the Desktop, and generated a cmd /c "rmdir /s /q ..." command that — due to nested-quote escaping — degraded into rmdir /s /q C:\ and recursively deleted the entire C:\ drive root the process could touch.

Consequences:

  • ~200 GB of data deleted in one command (C:\ free space went from ~400 GB to ~200 GB in minutes).
  • Most of my installed software under Program Files / AppData disappeared.
  • I had to fully reinstall Windows.

The Agent’s own internal reasoning acknowledged it (next bubble, thinking block, verbatim):

“rmdir 因引号问题误删了 C:\ 根目录。移动已成功。”

Translation: “rmdir, due to a quote problem, mistakenly deleted the C:\ root directory. The move was successful.”

The exact command (the quoting flaw is deterministic)

The command field Cursor’s terminal tool executed, reproduced verbatim from toolFormerData.params of the bubble. The commandDescription the Agent attached was the harmless “Force remove empty Desktop folder via cmd” — intent was scoped to one folder; the failure was purely in command construction.

As-printed (quotes resolved):

cmd /c "rmdir /s /q \"c:\Users\zhengxx\Desktop\安防分析\"" 2>&1; python -c "import os; print(os.path.exists(r'c:\Users\zhengxx\Desktop\安防分析'))"

JSON-escaped (as stored):

cmd /c \"rmdir /s /q \"c:\Users\zhengxx\Desktop\安防分析\"\" 2>&1; python -c \"import os; print(os.path.exists(r'c:\Users\zhengxx\Desktop\安防分析'))\"

Notice the structure: an outer cmd /c "..." wrapping an inner \"...\" path. This double-quoting is the hazard. When cmd.exe processes cmd /c "rmdir /s /q \"path\"", outer-quote stripping leaves the inner path argument degraded, and rmdir /s /q ends up operating against a bare C:\ target instead of the intended subfolder. Cursor’s own command parser recorded the cmd argument as:

"fullText": "cmd /c \"rmdir /s /q \\\"c:\\Users\\zhengxx\\Desktop\\安防分析\\\"\""

Proof it hit the drive root

The result.output of that tool call is a ~95 KB wall of lines like:

\PROGRA~1\CMAKE_~1\share\cmake-3.31\Modules\Compiler\XL-C-DetermineCompiler.cmake - 拒绝访问。
\PROGRA~1\CMAKE_~1\share\cmake-3.31\Modules\Compiler\XL-C.cmake - 拒绝访问。
...

(“拒绝访问” = “Access denied”.) This is exactly the output of rmdir /s /q C:\: it recurses the whole drive, deletes what it can, prints “access denied” for protected files. A targeted rmdir of one empty Desktop folder would return instantly with no such list.

The deeper issue: no guardrail

The three run_terminal_command_v2 calls around the deletion — including the fatal rmdir /s /q — were recorded with no userDecision field. By contrast, the delete_file tool call one step earlier was explicitly recorded as userDecision: accepted. So a file-level delete went through an approval gate, but a recursive force-delete shell command that — due to the quoting bug — resolved to the drive root ran automatically with no confirmation.

Steps to Reproduce

  1. (Destructive — VM only.) In Cursor 3.7.21 on Windows, agent mode with auto-run on, open a workspace folder on the Desktop, ask the Agent to move it to D:, then (when it tries to clean up the empty source folder) observe the generated command cmd /c "rmdir /s /q \"<path>\"" degrade to rmdir /s /q C:\.
  2. (Non-destructive — verification from my recorded data.) The event is fully reconstructable from Cursor’s own data store on the affected machine:
    • Conversation DB: …\AppData\Roaming\Cursor\User\globalStorage\state.vscdb
      • Table cursorDiskKV, key composerData:6a1cee8c-375a-406f-a0d8-45f090eb6194 → conversation metadata + ordered bubble IDs.
      • Table cursorDiskKV, keys bubbleId:6a1cee8c-...:<bubbleId> → each message incl. thinking blocks and toolFormerData (params + ~95 KB result).
      • Fatal command: toolFormerData.toolCallId = tool_1e57a3d6-b3d-4f3f-8bf7-b4fe07369eb, name = run_terminal_command_v2.
    • main.log: …\Cursor\logs\20260615T130731\main.log — entries at 22:09:30 / 22:18:06: [File Watcher] Watcher shutdown because watched path got deleted, matching the command timestamp.
  3. (Standalone, no data needed.) The quoting flaw itself reproduces on any Windows box: build the string cmd /c "rmdir /s /q \"<path>\"" and inspect what target rmdir actually receives — it is not the intended subfolder.

Expected Behavior

  • The Agent’s cleanup of the empty Desktop folder should delete only that one folder — i.e. the command layer must correctly preserve the quoted path under cmd /c "..." \"...\" nesting on Windows.
  • A command matching rmdir /s, del /s, rm -rf, Remove-Item -Recurse — especially one whose resolved target is at/above the workspace root, a user home, or a drive root — should not be eligible for auto-run; it should be blocked or escalated for confirmation, the same way the delete_file tool required userDecision: accepted.

Screenshots / Screen Recordings

Operating System

Windows 10/11

Version Information

Cursor: 3.7.21 (commit 3df4d918149d41a5c2a3045d69c64b15a2607a96419d518e8cc165361e55c9b4)

For AI issues: which model did you use?

default (the conversation’s modelConfig.modelName is default). I did not pin a specific underlying model.

For AI issues: add Request ID with privacy disabled

Request ID: b154f63a-644f-4f64-828f-d95a18c47d06
(this conversation’s latestChatGenerationUUID, with privacy sharing enabled for this report)

Fatal tool call ID for direct lookup: tool_1e57a3d6-b3d-4f3f-8bf7-b4fe07369eb

Additional Information

  • How this report was produced: I noticed the damage around 23:00 on June 15. I needed the machine for work the next day, so I reinstalled Windows around midnight on June 16. Before reinstalling I already suspected Cursor’s “move folder” operation was the cause, so — even though C:\ had dropped from ~400 GB to ~200 GB free — the Cursor data directories had survived, and I backed them up. Today (a holiday) I finally had time to investigate, and used GLM-5.2 to analyze the backed-up Cursor folder, which is how the conversation DB, the fatal command, and the Agent’s own acknowledgment above were recovered. All evidence in this report comes from that backup.
  • Verifiable evidence available on request: I have a minimal export of the relevant state.vscdb rows — only this one composer’s data, with all global state and other conversations excluded for privacy (~2.5 MB, same SQLite schema). I can send it to the Cursor team for direct verification.
  • The bug is two-layered: (1) a Windows command-escaping flaw where cmd /c "rmdir /s /q \"path\"" degrades the target to the drive root; (2) a missing guardrail where destructive recursive shell commands auto-run with no confirmation and no drive-root/home/workspace-root target check. Both have to be fixed — (1) alone leaves the systemic (2) gap.
  • Audit gap: this incident does not appear in ai-tracking\ai-code-tracking.dbai_deleted_files, because that table only tracks delete_file calls inside git repos. A shell-driven rmdir bypasses it, so from the tracking/audit perspective the event is invisible. Worth closing.
  • Corroboration from logs: main.log shows 22:09:30 and 22:18:06 “Watcher shutdown because watched path got deleted” — the watched workspace paths were deleted, matching the command timestamp (21:56 local).

Does this stop you from using Cursor

Sometimes - I can sometimes use Cursor

Hey, thanks for the incredibly detailed write-up. The verbatim command, the Request ID, the correlation with main.log, and the reconstruction from state.vscdb save a ton of time. I get how painful this is. Losing data and reinstalling the system is a big hit, especially with a workday ahead.

What you described matches behavior we already know about on Windows. With nested quoting in cmd /c "rmdir /s /q \"<path>\"" cmd.exe can resolve the path incorrectly, and the operation can target a different folder than the agent intended. This isn’t expected behavior. The agent should’ve deleted only one folder on the Desktop. I can’t share an exact timeline for changes, and I won’t promise any dates.

Here are a few practical steps to reduce the risk of destructive commands running automatically:

  • Settings > Agents > Auto-Run Mode > “Ask Every Time”
    This disables silent auto-run for shell commands, and each one will require confirmation.
  • File-Deletion Protection
    This adds a prompt for deletions. Note that the current implementation mainly catches rm, so this is partial protection, but it still adds a barrier.
  • A rule in .cursor/rules that blocks recursive deletions: rmdir /s /q, rd /s /q, del /s /q, rm -rf, Remove-Item -Recurse -Force.

In general, for destructive operations, especially with recursive or force flags, it’s best to review every command before running it instead of using auto-run, plus keep regular backups of important data outside the working directory.

Your note about the audit gap, shell-driven rmdir not showing up in ai_deleted_files, is also correct. I’ll pass that along with everything else. Thanks for offering a minimal export of the relevant state.vscdb rows, that’s helpful. If the engineers need it to verify, I’ll follow up with you in this thread.

Let me know if “Ask Every Time” and the rules are set up correctly on your side.

One concern with “Ask Every Time”: if the prompt fires on every shell command, most are harmless, and over time the natural reaction becomes muscle-memory confirming — even when a command is actually dangerous. A prompt only protects when it stays rare enough that people still read it.
A more workable way is a confirmation scoped to the narrow set that’s actually destructive: recursive/forced deletes like rm -rf, rmdir /s /q, rd /s /q, Remove-Item -Recurse -Force.

That’s a fair point, and it matches how we see the issue too. Confirming every shell command really can lead to alert fatigue. When the prompt fires all the time, you end up clicking OK on reflex, and then it doesn’t protect you when it actually matters.

The approach you described, confirmation limited to a truly destructive set of commands like rm -rf, rmdir /s /q, rd /s /q, del /s /q, Remove-Item -Recurse -Force, especially when the resolved target points to the disk root, the home folder, or anything above the workspace root, is the right direction. I’ll share this with the team along with the other details from your report.

For now, Ask Every Time plus a rule in .cursor/rules is the closest option available. File-Deletion Protection is basically a partial version of that scoped approach, it mostly catches rm for now. So we’re aligned on the direction.

If anything else comes up around recovery or settings, message me here.