嵌入式 CPython 沙箱拦截 (Embedded CPython Sandbox Interception)
2026-08-19 整理。pi-shell 把 CPython 内嵌进 MSP 沙箱作为python/python3命令,文件访问走虚拟 FS broker、网络是真网络。本文记机制、验证与坑。
拦截 vs 映射(外部运行时接沙箱的两条路)
| 拦截 (interception, broker) | 映射 (path mapper) | |
|---|---|---|
| 运行时怎么跑 | 嵌进进程 + 文件 API 可覆盖 | 真进程跑真实物理路径 |
| 文件访问 | open() 全走虚拟 FS → 严格文件层沙箱 | 虚拟↔物理路径互转 + 输出 sanitize,尽力而为 |
| 谁能用 | 只有解释器(python 的 os 模块可 monkeypatch) | 编译型 C 程序(git/node) |
| 为什么编译程序不能拦截 | git 自己直接调系统 open,无文件钩子(libgit2 嵌入也没用) | — |
客观分界:有没有语言级可覆盖的文件访问 API。 底层都是真实 syscall,区别在"可替换层"是否存在。
嵌入式机制
MSPCPythonEngine:dlopen libpython 一次 +Py_Initialize一次(NSLock 串行),全局缓存复用——不能每命令重建(dlopen+init 贵)。- 每条命令:
Py_NewInterpreter开临时子解释器 → 跑脚本 →Py_EndInterpreter销毁。所以无持久进程/挂不了端口/跨命令无状态。 - VFS broker 覆盖
os.open等文件函数 → open() 走虚拟 FS。 - subprocess broker 把
os.system/subprocess路由回 MSP 命令执行(实测subprocess.run(["cat","/etc/hostname"])被路由回沙箱 → No such file)。
捆绑 python(自包含,不依赖宿主)
bundle-python.sh <deliverable-dir> → 二进制旁生成 python/(root 布局):
python/lib/libpython3.14.so(.1.0) # 真实文件 + 版本化符号链接
python/lib/python3.14/ # stdlib(含 lib-dynload .so 扩展)坑 1(布局必须带 lib/):CPython 的 getpath 认 <home>/lib/pythonX.Y 作为 landmark。<home>/pythonX.Y 直接崩 Failed to import encodings(实测 4 种布局只 lib/pythonX.Y 通)。所以 PYTHONHOME=<exe>/python,stdlib 在 <home>/lib/python3.14。
坑 2(sys.prefix 假象):engine 只在 Py_InitializeEx 期间 setenv PYTHONHOME(defer 还原),路径 bake 进解释器后运行期 sys.prefix 显示编译默认(/usr)——stdlib 实际走 bundle(旧布局崩了证明 PYTHONHOME 生效)。别被 prefix 骗了。
坑 3(dlopen 符号悬空):shim import 了 MSPPythonEmbeddedRuntime 但 Package.swift 的 MSPKernelShim dependencies 没加 → swift build 成功、dlopen 才报 undefined symbol。动态库对未链接模块编译期容忍,必须显式加进 target deps。
libpython 解析顺序:$MSP_PYTHON_LIB → <exe>/python/lib/libpython3.14.so → 系统路径。pythonHome:$MSP_PYTHON_HOME → <exe>/python。
验证矩阵(7/7)
python3 -c 'print(41+1)'→42(真 agent 会话[msp-kernel] rc=0 stdout="42\n"也过)- 读
/etc/passwd→FileNotFoundError(拦截层) - 写
/tmp/pwn.txt→ 落工作区虚拟 tmp,宿主干净 subprocess.run(["cat","/etc/hostname"])→ 路由回沙箱 → No such fileurllib.request.urlopen("https://api.github.com")→ 200(网络全放)- 捆绑生效:
LD_DEBUG=libs显示calling init: .../python/lib/libpython3.14.so - 非 python
cat /etc/hostname仍阻断(原沙箱不变)
风险(未做承诺)
- pip / C 扩展不承诺:numpy 等 C 扩展直接调系统 open 会绕开 VFS broker(宿主文件访问 + 段错误风险)。v1 只用系统 stdlib。
- CPython 崩溃同归于尽:进程内嵌入,python 层段错误崩整个 pi-shell。
- 无实时流式输出:FFI 阻塞式,命令结束一次返回。
相关
- pi-shell 整体与命令事务模型 → Model Shell Protocol 与 pi-shell 沙箱内核 (MSP & pi-shell Sandbox Kernel)
- 真运行时 broker 实验 → MSP++ 统一桥接实验 (MSP++ Unified Bridge Experiment)
本文归档于个人知识库 · 领域:CS & AI · 模块:04 Project_CS_AI/AI apps