feat(ext): #1075 REQ-138 用 sandbox-exec wrapper 围住引擎 shell,越界写入 fail-closed - #1126
Merged
Conversation
…closed
C1 接缝(基线 §3):在 @alpha-code/ext 的 config(cfg) hook 里把 cfg.shell **包住**成
一个 Alpha wrapper —— wrapper 内 `exec sandbox-exec -f <profile>` 再 exec 用户真 shell。
收编上游 0 行。
咽喉点(全称否定式落成有限判据):到达「工具派生子进程真正落盘」的唯一通路是
cfg.shell → wrapper → sandbox-exec 加载 profile → 真 shell;profile 的
`(deny file-write*)` 之后只再放行一个闭集前缀(WORKDIR 参数 + profile 内登记的固定前缀),
其余写入在内核层 EPERM。判据于是有限、一次变异判得完。
不变量:
- I1 cfg.shell 恒指向 wrapper;装不上时顶成 deny stub / /usr/bin/false,绝不回落裸 shell。
- I2 可写闭集唯一权威 = shell-sandbox.ts 的 SEATBELT_PROFILE 常量(新增前缀改这里,可 diff)。
- I3 判据永远是「文件是否落盘」,不是子进程 exit code。
- I4 wrapper 对 argv 完全透传(`"$@"`),不解析、不重写。
落点:wrapper 与 profile 落 ALPHA_GLOBAL_DIR/{bin/<basename>,sandbox/alpha-shell.sb} ——
基线 §2.4 的 `<userData>/bin` 在 spike 里成立,但 C1 的 config hook 在 ext 包内拿不到
Electron main 的 userData;ALPHA_GLOBAL_DIR 是 ext 唯一能 canonical 校验的 alpha 自有可写根,
走它保持 ext-only、收编 0。架构文档 §7 已校正该路径假设。
证据(本机 macOS,真 sandbox-exec):越界写(写 $HOME 外目录)在围栏下 EPERM 且文件不落盘;
同一语料撤围栏后全部落盘(正反两跑)。类边界探针(重定向 >/>>、sh/python3/node 解释器、
nohup 脱离、指向工作区外的 symlink)围栏下全拦。打包 Electron sidecar 复跑归 [REQ-138][VERIFY]。
Out of scope(基线 §4):进程内 FS 工具 · MCP stdio · LSP · 网络(#1077)· Windows · pty。
Fixes#1075
Refs #1074
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QHDS2BFKuzm9uNH1svU2ojUh oh!
There was an error while loading. Please reload this page.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
做了什么
C1 接缝(基线
docs/architecture/2026-08-23-shell-sandbox-seam.md§3):在@alpha-code/ext的config(cfg)hook 里把cfg.shell包住成一个 Alpha wrapper —— wrapper 内exec /usr/bin/sandbox-exec -f <profile> -D WORKDIR="$(pwd)" <真shell> "$@"。收编上游 0 行(north-star 绿)。咽喉点(全称否定式 → 有限判据)
「没有任何进程能写到工作区外」没有有限证据集。本票把它改写成:到达「工具派生子进程真正落盘」的唯一通路是
cfg.shell→ wrapper → sandbox-exec 加载 profile → 真 shell;profile 的(deny file-write*)之后只再放行一个闭集前缀(WORKDIR 参数 + profile 内登记的固定前缀),其余写入在内核层 EPERM。判据于是有限、一次变异判得完。不变量
cfg.shell恒指向 wrapper;装不上时顶成 deny stub //usr/bin/false,绝不回落裸 shell。shell-sandbox.ts的SEATBELT_PROFILE常量(新增前缀改这里,可 diff;seam 测试逐 token 全等挡拓宽)。"$@"),不解析、不重写。落点(与基线 §2.4 的差异,已在架构文档 §7 校正)
wrapper 与 profile 落
ALPHA_GLOBAL_DIR/{bin/<basename>, sandbox/alpha-shell.sb},不落<userData>:C1 的 config hook 跑在 ext 包内,拿不到 Electron main 的app.getPath("userData");ALPHA_GLOBAL_DIR是 ext 唯一能 canonical 校验的 alpha 自有可写根 —— 走它保持 ext-only、收编 0。变异实验证据(本机 macOS,真
sandbox-exec)越界写(写
$HOME下、不在 profile 允许集里的目录)在围栏下 EPERM 且文件不落盘;同一语料撤围栏后全部落盘(正反两跑,基线 §2.6)。类边界探针 —— 重定向>/>>、sh/python3/node解释器、nohup脱离、指向工作区外的 symlink —— 围栏下全拦。测试(AC1–AC3)
alpha-sandbox-seam.test.ts(已登记 gate-files.tsv,精确 11 条):接线 + profile 闭集(逐 token 全等)+ fail-closed(注入写失败 ⇒ deny stub;再失败 ⇒/usr/bin/false)。platform 用 seam 强制 darwin、fs 用捕获式 mock ⇒ Linux CI 也跑。alpha-sandbox-escape.test.ts:真sandbox-exec正反语料,skipIf(!sandbox-exec)(CI/ubuntu skip、本机 macOS 真跑)。alpha-sandbox-reassert.test.ts(AC3):每次加载重新包裹 + 双重包裹防线(cfg.shell 已是 wrapper ⇒ real 回落默认,不自嵌套)。alpha-sandbox-shell-resolve.test.ts:resolveRealShell对真@opencode-ai/coreShell.acceptable+Shell.name的等价性锚(独立基准,枚举输入形状域;darwin only)。门(本机 CI 口径,实测全绿)
contracts-consumer/ext/ui-mac typecheck·check:vendor·ext floor 100(157 pass)·ui-mac floor 3000known-fails(4479 pass / 0 fail,base fail-set 差 = 0)·bun-test-app(exit 0)·north-star(0 upstream edit)·assert-gate-files(新 seam 行 =11 通过)· 三个 opencode 真插件装载集成测试(7/5/10 pass)全绿。Out of scope(基线 §4)
进程内 FS 工具 · MCP stdio · LSP · 网络(#1077)· Windows · pty。打包 Electron sidecar 复跑归
[REQ-138][VERIFY]。Fixes#1075
Refs #1074
🤖 Generated with Claude Code
https://claude.ai/code/session_01QHDS2BFKuzm9uNH1svU2oj