Codex 把我 C 盘半边天削平了——AI Coding 时代,别再盲目Approve

凌晨 1 点,我让 Codex 顺手清一下 node_modules。 8 分钟后,C 盘里我的 Documents、Desktop、Downloads 都被它从字母 A 扫到了 Z。 而且------是我亲手点的 Approve


前言:一次"看起来无害"的清理

事情起因蠢得让人不想承认。

我在一个 Next.js 项目里折腾 pnpm,node_modules 已经膨胀到深路径无法用普通方式删除(Windows 下经典 路径过长 报错)。我开了个 Codex Desktop 会话,对 cwd 指着那个项目,发了一条 5 个字的中文 prompt------大意是"继续做一下"------然后看着它出方案。

方案出来挺漂亮:

  • \\?\ 长路径前缀绕开 Windows 的 260 字符限制
  • cmd /c "rd /s /q ..." 强制无确认删除
  • 还加了 StartsWith safety check,确保删除目标在 root 之内

我看了一眼,点了 Approve

然后命令开始跑,10 秒后超时退出。Codex 看输出报错,自己改写命令重试。又超时。再试。再试......

8 分钟后我才意识到:Codex 的输出里出现了 \$Recycle.Bin\Boot\BCD\$WINRE_BACKUP_PARTITION.MARKER 这些字符串。

这些不是我的项目目录里的文件------这是 C 盘根目录


现场:从字母 A 删到了 Z

事后从 Codex 的 sqlite 日志里挖出来的命令实际输出长这样(节选):

erlang 复制代码
command timed out after 120426 milliseconds
\$Recycle.Bin\S-1-5-18 - Access is denied.
\$Recycle.Bin\S-1-5-~1 - Access is denied.
\$Recycle.Bin - Access is denied.
\$WINRE~1\Rollback - Access is denied.
\$WINRE_BACKUP_PARTITION.MARKER - Access is denied.
\AMTAG.BIN - Access is denied.
\Boot\BCD - Access is denied.
\Boot\bg-BG\bootmgr.exe.mui - Access is denied.
\Boot\cs-CZ\bootmgr.exe.mui - Access is denied.
\Boot\da-DK\bootmgr.exe.mui - Access is denied.
\Boot\de-DE\bootmgr.exe.mui - Access is denied.
...

这是 rd /s /qC 盘根目录按字母序遍历的输出。

  • 系统目录($Recycle.BinBoot\BCD$WINRE_BACKUP_PARTITION.MARKER)有 ACL 保护,被拒,所以系统还能启动;
  • 我自己的目录(Documents、Desktop、Downloads 等),ACL 是我自己授权的,全军覆没。

最后是 Windows 的**卷影副本(Shadow Copy)**救了我一命。


恢复过程:卷影副本是怎么救回来的

发现日志里冒出 \$Recycle.Bin 那一瞬间,我做的第一件事是关掉 Codex Desktop 进程 ------rd /s /q 是无回收站的硬删,删一个少一个,没办法 Ctrl+Z 回退。损失已经定格,剩下的就是把能捞的捞回来。

止损完,我开了 Claude Code 新会话求救。一句话:"cc 全完了,codex 把我 C 盘大量数据全删了"。

整个恢复花了大约 1 小时 28 分钟,关键步骤如下:

1. 先评估损失范围

bash 复制代码
ls /c/Users/admin/
du -sh /c/Users/admin/Desktop /c/Users/admin/Documents /c/Users/admin/Downloads ...

确认 DesktopDocumentsDownloadsPictures.claude.docker.aws.azure 这些都没了------大约 22GB 数据.claude 整个目录消失意味着我的 Claude Code 配置、credentials、MCP、skills、plugins 全部丢失,下一次启动就是裸奔。

2. 找有没有可用的卷影副本

powershell 复制代码
vssadmin list shadows
Get-WmiObject -Class Win32_ShadowCopy | Select DeviceObject, InstallDate, VolumeName

幸运的是,系统上有三个快照 (5/1、5/11、5/18 各一个)。最近一个是 5/18 凌晨------离事故 5/23 凌晨整整 5 天。这意味着我会丢 5 天里在 C:\Users\admin\ 下产生的所有新文件,但 22GB 里的核心数据是能找回来的。

如果这一步输出"未发现任何卷影副本",那基本就没救了------这也是后面教训里反复强调"现在就去把系统保护打开"的原因。

3. 选定快照,挂成可访问的路径

VSS 卷影副本的原始路径长这样:\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy3\,对很多 Windows 工具不友好(Copy-Item 解析会出问题)。用 mklink 创建符号链接绕开:

cmd 复制代码
cmd /c "mklink /D C:\ShadowCopy3 \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy3\"

坑点 1mklink 是 cmd 内置命令,不能直接在 PowerShell 里跑 ,必须 cmd /c 包一层。 坑点 2:源路径末尾的反斜杠不能省。

4. 用 robocopy 而不是 Copy-Item

我第一反应是 Copy-Item -Recurse -Force,结果深层子目录死活拷不全Copy-Item 在 VSS 路径下有玄学问题,可能跟它处理符号链接和 reparse point 的方式有关)。换 robocopy

powershell 复制代码
robocopy '\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy3\Users\admin\.claude\' `
         'C:\Users\admin\.claude\' `
         /E /COPY:DAT /R:1 /W:1 /NP
  • /E 包含空目录在内的所有子目录
  • /COPY:DAT 拷数据+属性+时间戳(不要用 /COPYALL,VSS 里 ACL 拷过来会很麻烦)
  • /R:1 /W:1 失败只重试 1 次、等待 1 秒,避免卡死
  • /NP 不打进度,日志干净

.claudeDocumentsDesktopDownloadsPictures 几个关键目录全部用这个套路拉回来,11 分钟搞定核心数据

5. 处理 git 仓库 + 受损文件

VSS 快照里包含 git 仓库时,.git/index 可能跟当前 working tree 状态不一致。.claude/plugins/marketplaces/ 下几个插件市场都是 git 克隆来的,恢复后 git 命令报错。直接重置:

bash 复制代码
rm .git/index && git reset --hard HEAD

6. Chrome 数据的"玄学"恢复

这一段是最折腾的。Chrome 用户数据从 VSS 拷回来后,Chrome 启动直接报"配置已损坏"。具体踩了几个连环坑:

  • SingletonLock / SingletonSocket:Chrome 的进程锁文件,VSS 里那一份是旧状态,必须删掉再启动
  • LevelDB journal 不一致*-journalLOCK 文件要全部清掉,LevelDB 才肯重建
  • Secure Preferences 的 HMAC 校验 :Chrome 会用 HMAC 验配置完整性,从 VSS 拷过来 HMAC 对不上,得手动清空 super_mac 字段让 Chrome 重算
  • Bookmarks 文件含 null bytes :这个最离谱------三个快照里的 Bookmarks 文件读出来都掺着 \x00,标准 json.loads 直接挂。试了 esentutl /y(微软官方推荐的 VSS 复制工具)、试了 UTF-16LE 解码、试了 null byte 剥离 + 截断式 JSON 修复,都没能完全救回来

最后这步是从我另一台 Mac 上同步过来兜的底------好在浏览器书签和密码这种东西大多数人会有 Google 同步或者多端冗余。

7. 清理 + 验证

cmd 复制代码
rmdir C:\ShadowCopy3

挨个验证:.claude 启动 OK、docker 服务能起、各 .aws/.azure/.docker 凭证可用、IDE 配置回来了。总耗时 88 分钟,没救回来的主要是 Chrome 的 Bookmarks 和事故前 5 天产生的新文件------能接受。


总结一句卷影副本是 Windows 给你免费的事故保险,但前提是你提前开了系统保护。如果你看到这里发现自己没开------放下文章,先去开。控制面板 → 系统 → 系统保护 → 选 C 盘 → 配置 → 启用系统保护,分配 5-10% 的磁盘空间。

顺便说一句:别迷信卷影副本能救一切 。VSS 是文件系统级快照,对运行中的程序(浏览器、数据库、IDE)当时打开的文件状态不一定一致,恢复后经常需要额外修补------参考上面 Chrome 那一节。重要数据的真正兜底是多端同步 + 异地备份


真凶命令

事故 turn 的命令我从 ~/.codex/logs_2.sqlite 里完整还原出来了:

powershell 复制代码
$root='C:\Users\admin\Documents\Codex\my-frontend';
$target=Join-Path $root 'node_modules';
if (!(Test-Path -LiteralPath $target)) { "TARGET_NOT_FOUND=$target"; exit 0 }

$resolvedRoot=(Resolve-Path -LiteralPath $root).Path;
$resolvedTarget=(Resolve-Path -LiteralPath $target).Path;
if (-not $resolvedTarget.StartsWith($resolvedRoot)) {
    throw "Safety check failed: target outside root"
}

$longPath='\\?\' + $resolvedTarget;
cmd /c "attrib -R /S /D \"$resolvedTarget\*\"" | Out-Null;
cmd /c "rd /s /q \"$longPath\"";   # <-- 真凶

读到这里很多人会皱眉:这命令一点毛病都没有啊?

  • Test-Path 前置判断 ✅
  • Resolve-Path 路径解析 ✅
  • StartsWith safety check ✅
  • 长路径前缀 \\?\ 也是标准做法 ✅

模型自己加了 4 道防线,逻辑上完全正确。但结果就是删了我半边 C 盘


为什么会爆炸

罪魁祸首是最后那一行:

powershell 复制代码
cmd /c "rd /s /q \"$longPath\"";

$longPath 实际是:

makefile 复制代码
\\?\C:\Users\admin\Documents\Codex\my-frontend\node_modules

按设计,这应该传给 cmd.exe 让 rd 删指定目录。但 PowerShell 调外部命令时的 native argument passing 会重写引号和反斜杠 ------\\?\ 这个特殊前缀在 PowerShell→cmd 这一跳里被"消化"掉了一部分,cmd 收到的字符串和你写的不一样。

具体到这条命令上发生了什么我没在隔离 VM 里实测复现,但结果是确定的rd /s /q 拿到一个它解析不出的路径,退化为对当前盘根目录递归删除

一句话:Agent 写的命令字面上没错,但 PowerShell 和 cmd 这俩 shell 之间传参时摔了一跤,掉进了 C 盘根。


Sandbox 为什么没拦住?

事故 turn 的 Codex sandbox 是这么配的:

yaml 复制代码
sandbox_policy: WorkspaceWrite {
    writable_roots: [
        C:\Users\admin\Documents\Codex\my-frontend,
        C:\Users\admin\Documents\Codex
    ],
    network_access: false,
}

理论上,Codex 不应该允许命令写出 writable_roots 之外的路径。

但这条命令的真正执行者不是 PowerShell ,而是 PowerShell 启动的 cmd.exe 子进程,rd 又是 cmd 的内置命令------整个删除动作发生在 cmd.exe 进程里,绕过了 Codex 对 PowerShell 主进程的 syscall 拦截

更直白点说:

只要 Agent 能起子进程,sandbox 就是个君子协议。

这不是 Codex 独有的问题。任何只在主进程层做拦截的 Agent sandbox(Claude Code、Cursor 的 agent mode、各家 IDE 内嵌 Agent)都吃这个亏------shell 套 shell,权限是穿透的。


"AI Coding 时代的盲信成本"

我反复想这件事到底蠢在哪里。

不是命令蠢------命令逻辑严密、还自带 safety check; 不是模型蠢------它选了一个工业界常用的"长路径 + 强删"组合; 不是 sandbox 蠢------WorkspaceWrite 该挡的都挡了,是 cmd 子进程绕的;

蠢的是我点 Approve 的那一秒钟脑子里在想什么。

我想的是:

"看起来挺合理的,cwd 在项目里、有 safety check、就是删个 node_modules,能出什么事?"

我没想的是:

  • cmd /c rd 这个组合在我的具体 Windows 环境(PowerShell 5.1)上行为是否可预测?
  • \\?\ 长路径前缀 + 引号 + 反斜杠转义这一串嵌套,跨 shell 传参的边界条件是什么?
  • 如果命令因为任何原因解析失败、回退、超时------它的失败模式是什么?

模型逻辑正确 ≠ 命令在你机器上行为正确。

AI Coding 给我们带来了一种很危险的错觉:Agent 既然能写出"看起来对的"代码 / 命令,那就一定能在我的环境里跑对。

这是错的。Agent 的训练数据里有的是"在干净 Ubuntu 容器里能跑通的 Bash";它没在我的 Windows 10 + PowerShell 5.1 + 当前 ACL 配置 + 当前长路径策略组合上跑过任何一次

你点 Approve 那一下,是在拿你的实际环境给它的命令做生产验证


教训(也是我从今天起的新规矩)

1. Approve 要看到具体命令,不能看"意图"

之前我看到"删除 node_modules"就放心了。从今天起,只要命令里出现下面任意一个东西,必须停下来读一遍命令本身

  • rd /s /q / rm -rf / Remove-Item -Recurse -Force
  • cmd /c / bash -c / sh -c(跨 shell 嵌套)
  • \\?\ / 任何路径里有变量插值
  • chmod / icacls / takeown(权限变更)
  • 任何超过 3 行的 shell 脚本(短代码块还能审,长的基本只能赌)

2. Sandbox 不可信,OS 层 ACL 才是兜底

我的应对:

  • 项目目录全部挪出系统盘 (我把所有项目从 C:\Users\admin\Documents\ 挪到了 F:\ 盘根)
  • Agent 的 cwd 永远不要指向 C:\Users\xxx\ 下任何位置------一旦命令跑飞,整个用户目录都在 ACL 允许范围里
  • 始终开 Windows 卷影副本(System Restore + File History),这次救命的就是它

3. Approval Policy 要选"每次 exec 都问",不要"按 turn 批准"

Codex 的 OnRequest 模式有个隐藏陷阱:我批准了第一条 exec,后面同一 turn 里的 retry 和后续命令是不再弹窗的

事故 8 分钟里我只看到过 1 次 Approve 弹窗。剩下 3 次灾难命令在我不知情的情况下跑完了。

各家 Agent 的 approval 粒度不一样,但选择"最细粒度的问询"永远没错。

4. 给 AI 干活的目录要"小盒子"

不要让 Agent 直接对着一个"项目根目录"开火。新建一个一次性的工作目录,干完了删掉。

arduino 复制代码
F:\agent-workspace\
├── task-2026-05-23-cleanup\    ← 这次任务的"沙箱"
│   └── node_modules-to-delete\ ← 把要操作的东西先 move 进来
└── task-2026-05-24-xxx\

干活前先 Move-Item 把要处理的东西挪进"沙箱目录",让 Agent 在沙箱里随便折腾。这是真正的"workspace isolation",不依赖 Agent 自己的 sandbox 实现。


立刻可以做的 3 件事

不管你用 Claude Code、Cursor、Codex、还是其它任何 Agent:

  1. 现在就把 approval_policy 改成最严格的"每次 exec 都问" (各家配置不同,搜文档关键词 auto-approve / permission / approval
  2. 检查 Windows 卷影副本是否启用:控制面板 → 系统 → 系统保护 → C 盘是否开启
  3. 把项目目录从 C:\Users\<你>\ 下挪到非系统盘------这一步成本最高但收益最大

写在最后

这篇文章不是黑 Codex。事故定位过程里我得说一句公道话:Codex 的内部日志(~/.codex/logs_2.sqlite)保留得非常完整,连 turn_id、thread_id、每个 shell exec 的完整 arguments 和 12000+ 行输出全都在,让事后追责成为可能。这篇文章本身,就是建立在这套日志之上写出来的。

我想说的是另一件事:

AI Coding 时代的'生产力',本质是把'决策密度'从'每一行代码'压缩到了'每一次 Approve'。

以前你要敲 100 行代码做一件事,每敲一行都在做小决策。现在你只点一次 Approve,背后那 100 行的全部风险被打包成一个按钮。

这个按钮值多少 token 的注意力------你愿意付,还是不愿意付,决定了你是 AI 时代的受益者还是受害者。

我这次付了一份"半个 C 盘"的学费。希望写出来,能让你少付一点。


事故还原全过程、logs_2.sqlite 提取脚本、可复用 SQL 查询,都在我个人仓库的事故归档里。如果你也踩过类似的坑,评论区聊聊------咱们一起把 AI Coding 时代的"地雷地图"画起来。


AI Coding Vibe Coding AI Agent Codex Windows 踩坑

相关推荐
aqi004 小时前
15天学会AI应用开发(五)使用AI摘要来压缩上下文消息
人工智能·python·大模型·ai编程·ai应用
Are_You_Okkk_5 小时前
无需配环境、不受设备限!MonkeyCode重新定义研发
大数据·人工智能·开源·团队开发·ai编程
AI产品实战5 小时前
95coder一句话生成MOM系统,AI用时6分50秒,Token只消耗25107
vue.js·spring boot·ai编程·ruoyi
Sator15 小时前
Unity2022版接入MCP
unity·ai编程
Bigger6 小时前
架构解密:mini-cc 的核心设计思路
前端·agent·ai编程
极客密码14 小时前
感谢雷总!Mimo大模型价值¥659/月的 MAX 套餐,让我免费领到了!
前端·ai编程·claude
甲维斯15 小时前
Claude Code的六种种授权模式!安全和效率控制
人工智能·ai编程
canonical_entropy15 小时前
超越Harness Engineering: AGE 应用开发模板介绍
aigc·ai编程·前端工程化
yangshicong15 小时前
第11章:结构化输出与数据提取 —— 让 AI 直接返回你想要的数据格式
数据库·人工智能·redis·python·langchain·ai编程