37 lines
4.3 KiB
Markdown
37 lines
4.3 KiB
Markdown
# 沙盒 Node 子进程与临时目录修复(2026-10-18)
|
|
|
|
## 已确认的问题与修复
|
|
|
|
继续实现[只读文件桥](沙盒只读文件桥接入-2026-10-18.md)时,真实测试发现三个独立问题:
|
|
|
|
1. Windows 把 AppContainer 内的 TEMP 派生为私有 `LOCALAPPDATA/Packages/<profile>/AC/Temp`;最初只创建了 `stage/tmp`,派生目录不存在,Node 临时文件创建返回 ENOENT。runner 现已在启动和授予 ACL 前创建对应私有目录,仍随本次 stage 清理。
|
|
2. 当前受测 Node 的默认同步管道捕获会在实际 AppContainer 中挂起,甚至其自身 timeout 尚未有效结束该启动;最终由外层 Job 时限终止。继承 stdio 和传入文件描述符的同步捕获均可用。提供显式预加载的自有适配器,用私有临时文件描述符交给原版 Node spawn 实现,保持原 token/Job/网络约束。
|
|
3. Python 3.13 起的 Windows `mkdir(0o700)` 创建显式 user/admin DACL,没有 AppContainer SID;真实 Python 3.14.7 的 TemporaryDirectory 因此创建后立即不可访问。新增只读 `python-sitecustomize.py`,仅对当前私有 stage 内的 0o700 建目录改为继承原生私有父 DACL;stage 外仍用原行为,访问继续由系统 ACL 拒绝。
|
|
|
|
未将该问题归因于已证明的 Windows/Node 内部机制:当前证据只证明上述允许/失败路径。未修改用户安装的 Node、libuv 或全局设置,也未回退宿主执行。
|
|
|
|
## 使用与维护
|
|
|
|
```json
|
|
{
|
|
"command": "node --require \"%YCODE_SANDBOX_PROCESS%\" build.cjs",
|
|
"runtimes": ["node"]
|
|
}
|
|
```
|
|
|
|
源文件是 `native/sandbox/node-process.cjs`。随 `sandbox:build` 复制到资源目录,manifest 记录源码和成品摘要;每次选择 Node 时校验、复制到只读 tools 目录。适配器通过显式 `--require` 或 require 启用,不更改宿主 Node 设置,不自动覆盖所有项目的运行方式。
|
|
|
|
启用后覆盖该 Node 进程公开的 `spawnSync`、`execFileSync`、`execSync`,并同步 ESM 内建命名导出。子进程依然由 Node 原生启动,AppContainer/Job 继承和系统 ACL 继续生效。默认捕获及 `stdio: 'pipe'` 使用私有输入/输出文件,其他显式 stdio 配置交给原实现。私有文件句柄在操作后关闭,文件和空目录尽力移除;最终 stage 清理负责收尾。
|
|
|
|
输入与 maxBuffer 各限制为最多 16 MiB;默认 maxBuffer 为 1 MiB。适配器按上限读取捕获内容,超限返回 ENOBUFS。这里是结果缓冲限制,不是子进程运行中的磁盘硬限额;超限检测发生于子进程返回后,不能由 ENOBUFS 推断进程在产生超量输出时已被终止。timeout 继续交给 Node 原生实现,整个进程树另由外层 Job 管理。
|
|
|
|
## 当前验证
|
|
|
|
`npm run test:sandbox:process` 最终 20/20 通过,报告 `.tmp/sandbox-process-9EyXTm/report.json`。测试使用隔离状态与运行时,真实执行 Node 同步二进制/stdin/错误/cwd/env/超时、继承 stdio、ESM 导出、缓冲上限、临时文件清理、原生 ACL、宿主文件拒绝,Python tempfile/subprocess/0o700 和宿主路径拒绝,以及三个资源被篡改时安装状态/命令共同拒绝。
|
|
|
|
已保留的原始诊断:`.tmp/sandbox-spawn-compat.log`(默认捕获超时)、`.tmp/sandbox-spawn-compat-default-fixed-temp.log`(创建 TEMP 后默认捕获仍超时)、`.tmp/sandbox-spawn-compat-files-fixed-temp.log`(文件描述符捕获成功)、`.tmp/sandbox-spawn-compat-adapter.log`(显式适配后 Node/宿主专用读取器的捕获与拒绝均成立)。
|
|
|
|
该适配器不是完整 child_process 复刻。异步 spawn/fork/IPC、流式事件/背压、额外 fd、所有 stdio/平台版本组合及输出磁盘硬限额继续待验;不启用适配器的默认 Node 管道仍有上述已知问题。P2/P5 不因此标记完成,也没有原版等价结论。
|
|
|
|
Python 适配器通过受控 PYTHONPATH 加载,具有清单摘要和只读 tools ACL。它不提供宿主目录授权,不修改宿主 Python;`-I/-S` 等绕过 site/PYTHONPATH 的方式也会绕过兼容修复。这里保留父 DACL 的私有范围,不宣称 POSIX mode/元数据完全兼容。原生行为依据是 [Python os.mkdir 文档](https://docs.python.org/3/library/os.html#os.mkdir) 对 Windows 0o700 及 3.13 变更的说明;该行为与 AppContainer 的组合失败及修复效果由隔离实测记录。
|