Replies: 5 comments
|
Confirmed against master's |
|
我基于当前 master 47f9438 完成了一个可直接审阅或 cherry-pick 的修复:
修复在执行 rmSync 之前拒绝任何解析到仓库根目录或其祖先目录的输出路径,因此覆盖空字符串、点号、双点号以及文件系统根目录;正常的子目录和同级输出仍然可用。 回归测试不是 mock rmSync,而是在 mkdtemp 创建的一次性 fixture 中执行真实 TypeScript release 脚本。空 --out 和 --out .. 在修复前分别删除 fixture sentinel,修复后均 fail fast 并保留 sentinel。focused test 2/2 通过,pre-push typecheck 通过。 |
|
Reviewed the fix — the ancestor-guard is stronger than the minimal |
|
Thanks — this prompted a deeper filesystem-semantics check. There is an important distinction:
I reproduced a worst-case bypass against the first commit. In a disposable Follow-up commit: yha9806@b8f2957 Branch: https://github.com/yha9806/deepseek-harness/tree/codex/fix-release-pack-out-guard The guard now checks both lexical containment and the canonical deletion target derived from the nearest existing destination parent, while deliberately not following the final path entry. This preserves ordinary missing output directories and final-link deletion semantics, but rejects ancestor symlink or junction paths that route deletion through the repository. Verification:
Remaining boundary: this provides fail-fast protection against static misconfiguration. A hostile same-user process could still replace an ancestor after validation, so it is not a race-free filesystem security boundary. |
|
The follow-up is excellent — my "optional hardening note" turned out to be a real hole, and you proved it: an intermediate-ancestor symlink ( |
Uh oh!
There was an error while loading. Please reload this page.
概述
scripts/release/pack.ts对--out参数解析后没有空值/根路径守卫,rmSync(destination, { recursive: true, force: true })会直接递归删除仓库根目录。位置
scripts/release/pack.ts:47-51(基于 master47f943859)复现
Node 的
path.resolve(root, '')返回值与resolve(root, '.')相同(即 root 本身),而 parseArgs 接受--out '':CI 中
--out "$RELEASE_DIR"在RELEASE_DIR为空环境变量时同样触发。对比:仓库内其他破坏性脚本都有守卫,唯独此处缺失
scripts/clean.ts:删除前断言目标为后代路径,并解析祖先符号链接防止逃逸scripts/release/verify-built-package-invariants.mjs:只删除自己mkdtemp出来的目录建议修复
rmSync之前拒绝destination === resolve(root, '.')(以及空values.out),守卫风格与 clean.ts 对齐即可,一行修复。影响
数据丢失(本地未提交改动、CI 工作区),后果不可逆。触发前提是操作员失误或空环境变量,但 release 脚本正是最容易出现这类输入的地方。
本问题由多轮 AI 辅助代码审查发现,并经两个独立外部模型(Claude Opus 4.8 / GPT-5.6,均 high reasoning)交叉读码复核,三方一致确认。
All reactions