refactor(exec,io): 文件沙箱单入口收进 io 工具、删 exec.FileSandbox(裁决 13.4.4)+ 修一条假阳性安全断言

- 删除未接线的 exec.FileSandbox(含 5 个用例):文件沙箱从此只有 plugins/tools/io/file.go 一处实现
- io 侧取更严一侧:NUL 拒绝(原 io 缺)、写前按最深存在祖先判定落点(避免越界建目录)、roots 归化到真实路径(修 roots 自身是 symlink 时的全误拒)
- exec/sandbox.go 保留并注释说明:那是**终端工作目录守卫**的原语(terminal.go 在用),不是文件沙箱
- 修假阳性:原 NUL 用例断言错误文本含 "NUL",而 t.TempDir() 目录名自带测试函数名 "…RejectsNULBytePath…"、错误又内嵌整条临时路径 ⇒ 删掉安全检查用例照样绿。改为哨兵错误 ErrNullByte + errors.Is(错误文本逐字节不变),修复后同一变异必红
- 同类排查:file_test.go 三处文本断言判定无风险(含空格的串不可能出现在临时目录名里),保留
This commit is contained in:
AskaEth committed 2026-10-04 12:29:39 +08:00
1 parent 95f97f5df3
commit 09ee561aa7
6 files changed
+344 -222

No files matched your search

+5
View File
@@ -6,6 +6,11 @@ import (
"strings"
)
// 本文件是终端沙箱的路径收敛原语(roots 清洗、词法包含判定、symlink 逃逸解析),
// 由 terminal.go 用于工作目录守卫。**它不是文件沙箱**:文件读写的沙箱已按裁决
// 13.4.4 收敛到 plugins/tools/io 文件工具(design/04 §4)。两侧保持同一收敛口径:
// 词法 roots 包含 + 最深存在祖先的 symlink 解析 + NUL 拒绝。
// absCleaners returns a slice of absolute, clean paths from raw roots. Dirty or
// empty entries are dropped; non-absolute roots are made absolute against the
// process working directory.