[Windows] Agent Shell: rmdir /s with trailing \ before " escapes target and wipes volume root

Where does the bug appear (feature/product)?

Cursor IDE

Describe the Bug

Priority: P0 — Agent Shell safety (platform), not “prompt hygiene”
Where: Editor / Agent Chat (in-editor Agent + Task subagent) + Terminal & commands


Summary

On Windows, a Cursor Task subagent ran Agent Shell:

cmd /c "rmdir /s /q \"d:\Cursor_Projects\quiz-check\_tmp_xlsx_inspect\""

Intent: delete one temp folder after Excel→MD conversion.
cwd of that Shell session was inside the folder being deleted (D:\Cursor_Projects\quiz-check\_tmp_xlsx_inspect).

Due to Windows cmd quoting (\ before closing " escapes the quote) combined with /s /q and cwd-inside-target, recursion escaped the declared target and walked the volume root D:\.

In ~40 seconds USN recorded ~210,201 FILE_DELETE events. Unlocked files on the work volume were wiped; locked paths (running Cursor, cwd, some .venv binaries) remained as skeletons. Agent treated exit_code: 32 + TMP_STILL_EXISTS as “cleanup failed,” while stderr already showed volume-root paths (\CursorData, \Program Files\cursor, \System Volume Information).

This is a platform safety gap in Agent Shell on Windows: destructive recursion must not be able to leave the declared target, and stderr outside-target paths must abort/surface hard failure.


Environment

Field Value
OS Windows 10/11
Cursor version 3.13.25
Workspace D:\Cursor_Projects\quiz-check
Model Grok 4.5 High (cursor-grok-4.5-high)
Features in-editor Agent + Task subagent + Shell tool
Incident local time 2026-07-28 19:58:11–19:58:52 Omsk (UTC+6)
Incident UTC 2026-07-28 13:58:11–13:58:52

IDs

ID Value
Request ID (primary subagent run, ~19:51 Omsk) 21363e0a-106d-4eb3-be2b-1d2ce262f9e6
Request ID (tool call at rmdir start, ~19:58:11) bacf250d-bff4-49e3-88c7-f405b64d63b0
Request ID (subagent completion after wipe, ~19:58:55) d09dcf84-5df4-4899-96d4-21ea4057902c
Parent chat 848c746d-a51a-4aa7-8940-557828b9067a
Subagent e51e8558-3f0b-4dab-9eca-e7374d8c1140
Terminal session 618164 (pid 33664)

Privacy: Share Data enabled.


Exact Shell metadata (terminal 618164)

cwd:        D:\Cursor_Projects\quiz-check\_tmp_xlsx_inspect
command:    cmd /c "rmdir /s /q \"d:\Cursor_Projects\quiz-check\_tmp_xlsx_inspect\""
started_at: 2026-07-28T13:58:11.439Z
ended_at:   2026-07-28T13:58:52.263Z
elapsed_ms: 40824
exit_code:  32
marker:     TMP_STILL_EXISTS

stderr path classes (volume-root walk — not limited to temp)

  • \CursorData\...
  • \Cursor_Projects\... (incl. other repos / .venv)
  • \Program Files\cursor\...
  • \System Volume Information

Root cause (as observed)

  1. Windows quoting: "D:\path\folder\" — trailing \ before " escapes the closing quote; path parsing breaks.
  2. cwd inside target: Shell cwd = folder being deleted with rmdir /s /q.
  3. /s /q: recursive + quiet → mass deletes succeed silently; only failures print.
  4. Agent interpretation: exit_code: 32 / sharing violation / TMP_STILL_EXISTS treated as benign cleanup failure despite stderr showing outside-target volume-root paths.

Not the cause

  • Disk failure / NTFS corruption (volume stayed online; after reboot Ntfs healthy)
  • Wise / cleanmgr / intentional format (0 hits in System/Application 18–21 Omsk)
  • AppData→D: junction as intentional wipe tool
  • Explicit user command to wipe D:\

Impact

  • Work volume D: largely emptied of unlocked data (~75+ GB free after; only Cursor remnants visible at top level).
  • USN peak ~210k deletes / ~40s.
  • Cursor main.log @ 19:58:23: Watcher shutdown because watched path got deleted.
  • SSD TRIM: many recovered MFT entries zero-filled → poor undelete prospects.
  • Cursor marked unusable for normal work until environment rebuilt.

Follow-up attachments after post: proof_rmdir_peak.txt, main_log_watcher_1958.txt.


Ask

Treat as P0 Agent Shell safety on Windows, not user error. Please harden Shell path handling + cwd-vs-target checks + outside-target stderr abort for recursive deletes.


Steps to Reproduce

WARNING: disposable VM/volume only. Never on a real work disk.

  1. Create D:\repro_safe\_tmp_xlsx_inspect\ with dummy files.
  2. Agent Shell cwd = that folder.
  3. Run: cmd /c "rmdir /s /q \"D:\repro_safe\_tmp_xlsx_inspect\""
  4. Observe recursion escaping toward volume root; stderr may show \CursorData, \Program Files, \System Volume Information.

Safer contrast: cd to a parent above the target first; path without trailing \ before closing ".

Expected Behavior

  1. Block recursive deletes (rmdir /s, Remove-Item -Recurse, rm -rf) when cwd is inside the delete target.
  2. Normalize Windows paths so trailing \ before " cannot widen delete scope.
  3. Hard-deny recursive deletes of volume roots / sensitive trees (D:\, \System Volume Information).
  4. Abort and surface hard failure if stderr shows paths outside the declared target (do not treat as “temp busy”).

Ask: Treat as P0 Agent Shell safety on Windows, not user error. Please harden Shell path handling + cwd-vs-target checks + outside-target stderr abort for recursive deletes.

Operating System

Windows 10/11

Version Information

Version: 3.13.25 (user setup)
VS Code Extension API: 1.128.0
Commit: 31e8d61c448c7472e371505838a0fe34083dad50
Date: 2026-07-28T06:17:45.069Z
Layout: IDE
Build Type: Stable
Release Track: Default
Electron: 40.10.3
Chromium: 144.0.7559.236
Node.js: 24.15.0
V8: 14.4.258.32-electron.0
xterm.js: 6.1.0-beta.256
OS: Windows_NT x64 10.0.22621

For AI issues: which model did you use?

Grok 4.5 High (cursor-grok-4.5-high), Task subagent + Shell

For AI issues: add Request ID with privacy disabled

21363e0a-106d-4eb3-be2b-1d2ce262f9e6

Additional Information

USN ~210201 FILE_DELETE in ~40s. Terminal 618164, subagent e51e8558-…, parent 848c746d-…. Attachments after post: proof_rmdir_peak.txt, main_log_watcher_1958.txt

Request IDs (Share Data enabled):

  • Primary subagent run (~19:51 Omsk / 13:51 UTC): 21363e0a-106d-4eb3-be2b-1d2ce262f9e6
  • Tool-call window at rmdir start (~19:58:11 Omsk / 13:58:11 UTC): bacf250d-bff4-49e3-88c7-f405b64d63b0
  • Subagent completion right after wipe (~19:58:55 Omsk / 13:58:55 UTC): d09dcf84-5df4-4899-96d4-21ea4057902c

Local correlation IDs:

  • Parent chat: 848c746d-a51a-4aa7-8940-557828b9067a
  • Subagent (composer): e51e8558-3f0b-4dab-9eca-e7374d8c1140
  • Terminal session: 618164 (pid 33664)

Does this stop you from using Cursor

Yes - Cursor is unusable

Evidence attachments (no secrets / no C:\Users\… paths in these two):

main_log_watcher_1958.txt (4,7 КБ)

proof_rmdir_peak.txt (10,6 КБ)

Local mitigation we put in place (User Hooks)

Not a Cursor fix — a local hard gate until platform hardening lands.

What we installed

User-level Cursor hooks (~/.cursor/hooks.json), so they apply to parent agent and subagents in all projects — not always-on chatter, only on delete-like actions.

hooks.7z (3,1 КБ)

Archive: hooks.7z → extract to ~/.cursor/ (hooks.json + hooks/*.mjs). Requires node in PATH.

  1. beforeShellExecutionsafe-delete-shell.mjs
    Matcher: rmdir, rd, Remove-Item, rm -r, del /s, rimraf, rmtree, git clean, etc.

  2. preToolUsesafe-delete-tool.mjs
    Matcher: Delete tool

Policy

Decision When
deny cwd is inside / equal to the recursive delete target (our incident pattern)
deny trailing \ before closing " in the delete path (Windows quote escape)
deny delete target is a drive root (D:\, C:\, …)
ask any other delete / recursive cleanup (user must confirm)
allow non-delete commands

On deny/ask the hook injects a short SAFE DELETE POLICY back to the agent (cd above target first; no trailing \ before "; never widen scope on retry; stop if stderr shows volume-root paths like \System Volume Information).

Why this maps to the incident

Our wipe was:

cmd /c "rmdir /s /q \"d:\...\ _tmp_xlsx_inspect\""

with cwd inside that folder. The hook would have denied that combination (cwd∈target + trailing-\" pattern).

Limits (honest)

  • Fail-open if the hook script crashes (Cursor default) — keep the scripts simple.
  • Does not replace backups / Ask Every Time / File-Deletion Protection.
  • Does not fix Agent Shell quoting itself — only blocks the dangerous class locally.
  • Prefetch/process attribution still won’t come from USN; this is prevention, not forensics.

Ask to Cursor

Platform should still implement the same checks natively (cwd-vs-target, quote normalization, root deny, abort on outside-target stderr). Local hooks are a stopgap for users who already hit this class of failure.

Hey @Aleksey_Nm

This isn’t something you misconfigured, and your read on the cause is right: on Windows that cmd /c "rmdir /s /q \"…\"" quoting can collapse so the delete resolves to the drive root. It’s a pattern we’re aware of and tracking - no timeline to share, but I’ll follow up here if there’s an update.

On recovery I won’t give false hope: after a recursive delete on an SSD, TRIM usually zeroes the freed blocks, so undelete tools mostly return empty file shells. If any affected drive still holds something you need, stop writing to it entirely.

For prevention on Windows (no terminal sandbox there): keep destructive commands behind manual approval - Settings > Agents > Approvals & Execution, and don’t allowlist rmdir/rd/del/Remove-Item/cmd - lean on your hooks (the strongest gate here), and keep Git/backups as the safety net. Anything account-specific, email [email protected]. More on modes: Run Modes.