← 返回信息流
AI 资讯Hacker News·3 小时前

利用 MicroPython 和 WASM 在沙箱中运行 Python 代码

原标题:Running Python code in a sandbox with MicroPython and WASM

速览

本文探讨了结合 MicroPython 与 WebAssembly (WASM) 技术,在浏览器等沙箱环境中运行 Python 代码的方法。这种方案利用 WASM 的高性能和隔离特性,为 Python 提供了安全的执行环境。该技术在 Web 应用开发和远程代码执行场景中具有重要应用价值。

AI 深度解读

在沙箱中运行 Python 代码:MicroPython 与 WASM 的实验

背景

作者长期致力于探索在沙箱环境中运行代码的最佳方案,旨在解决开源项目(如 Datasette、LLM 和 sqlite-utils)中插件系统的安全隐患。这些项目均支持插件扩展,虽然插件机制极大地降低了新功能引入的风险,允许软件快速迭代而无需严格审查每一个 Pull Request,但其底层实现依赖于 Python 和 Pluggy。

目前,插件代码在应用程序中拥有完全的执行权限。这意味着任何存在缺陷或恶意的插件都可能导致系统崩溃或私有数据泄露。作者渴望一种能够隔离执行环境的方法,使得插件代码无法读取未授权文件、无法连接网络,从而避免对宿主应用程序或用户计算机造成危害。

除了插件场景,作者还希望在 Datasette 中支持更多需要任意代码执行的功能,例如定时任务:从受信任源获取 JSON 数据,通过简短代码将其转换为字典列表,并插入 SQLite 数据库。

核心内容

为了实现上述目标,作者定义了一套严格的沙箱需求,并经过对比后选择了 WebAssembly (WASM) 结合 MicroPython 的技术路线,最终发布了名为 micropython-wasm 的 Alpha 版本包。

沙箱的核心需求

作者对沙箱环境提出了以下具体指标:

  1. 依赖管理:必须能通过 PyPI 干净地安装,支持多平台的二进制 wheel,用户无需执行额外步骤。
  2. 资源限制:执行代码必须受到内存和 CPU 时间的严格限制,防止无限循环(如 while True: s += "longer string")导致应用或主机崩溃。
  3. 文件访问控制:要么完全禁止文件系统访问,要么由沙箱精确控制读写权限。
  4. 网络访问控制:禁止未经控制的网络通信,所有交互需经过宿主完全控制的层。
  5. 宿主函数交互:必须支持暴露特定的平台功能给沙箱内的代码。
  6. 稳定性与文档:项目必须健壮、受支持且文档清晰,避免使用那些标有“非活跃维护”警告的项目。

技术选型:为何选择 WebAssembly

虽然 JavaScript 引擎(如 V8)在浏览器中运行不可信代码方面经验丰富,但其复杂性极高,且难以嵌入到其他项目中。作者发现大多数 Python 集成 V8 的项目维护频率低,且明确警告不要用于完全不可信的环境。

相比之下,WebAssembly (WASM) 从设计之初就支持沙箱特性,并在浏览器中经过近十年的验证。wasmtime Python 库将 WASM 引入 Python 生态,活跃维护且提供二进制 wheel,是理想的选择。

为何选择 MicroPython

要在 WASM 中运行 Python,需要编译一个完整的 Python 解释器。

  • Pyodide 的局限:虽然 Pyodide 提供了优秀的浏览器端 Python WASM 支持,但其官方建议指出它仅适用于浏览器或 Node.js 环境,不支持服务端 Python。
  • MicroPython 的优势:MicroPython 是 Python 3 的精简高效实现,专为微控制器和资源受限环境优化。作者认为 WASM 环境本质上也是一种“资源受限环境”,因此 MicroPython 是更合适的候选者。

构建过程与突破

作者利用 AI 编程助手(GPT-5.5 Pro 和 Codex Desktop)加速了原型开发:

  1. 基础编译:通过研究 MicroPython 对 WASI 的实验性支持 PR,AI 生成了编译自定义 WASM 版本 MicroPython 的脚本,成功构建了原型库。
  2. 解决状态持久化难题
    • 问题:默认的 WASM 构建是一次性的,解释器启动、运行代码后随即停止,无法保留变量和函数状态。
    • 解决方案:通过 AI 协助,作者设计了一种基于队列的机制。在 Python 端,MicroPythonSession 启动一个线程处理请求队列;在 WASM 内部,MicroPython 解释器阻塞等待一个名为 __session_next__() 的宿主函数返回下一行代码,执行 eval() 后通过 __session_result__ 返回结果。这使得变量可以在多次 session.run() 调用之间保持驻留内存。
  3. 实现宿主函数交互
    • 为了允许沙箱代码调用宿主功能,作者通过 C 语言编写了底层逻辑(约 78 行代码),编译进最终的 362KB WASM 二进制文件中。这允许 Python 库选择性地向 MicroPython 暴露特定功能。

使用示例

开发者现在可以像使用普通 Python 会话一样使用 micropython-wasm

from micropython_wasm import MicroPythonSession

with MicroPythonSession() as session:
    print(session.run("x = 10\nprint(x)").stdout)
    print(session.run("x += 5\nprint(x)").stdout)
    print(session.run("print(x * 2)").stdout)

关键要点

  • 安全性优先:通过 WASM 隔离执行环境,从根本上解决了 Python 插件系统因拥有完全权限而带来的安全风险(如数据泄露、系统崩溃)。
  • 技术栈组合wasmtime + MicroPython + WASI 是实现服务端 Python 沙箱的有效组合,克服了 Pyodide 仅限浏览器端的限制。
  • AI 辅助开发:作者利用 GPT-5.5 和 Codex Desktop 快速解决了复杂的底层问题,包括 WASM 编译脚本生成、基于队列的状态持久化机制设计以及 C 语言宿主函数的实现。
  • 资源高效:最终生成的 WASM 二进制文件仅为 362KB,且通过队列机制实现了轻量级的状态保持,满足了资源受限环境的需求。
  • 可控的交互接口:通过精心设计的宿主函数(Host Functions),沙箱代码可以在受限范围内与外部环境进行安全交互,既保证了隔离性,又保留了功能性。

意义与影响

micropython-wasm 的推出为 Python 生态系统提供了一种新的安全代码执行范式。对于像 Datasette 这样依赖插件扩展的开源项目而言,这一技术使得“零信任”插件架构成为可能,极大地降低了第三方代码引入的安全风险。

此外,该方案证明了利用 AI 编程助手可以快速构建复杂的底层系统原型,降低了 WASM 和 C 语言等低层级技术的开发门槛。随着 WebAssembly 在服务端应用的普及,这种轻量级、高隔离性的沙箱方案有望被更广泛地应用于 Serverless 函数、在线代码编辑器、自动化测试平台等需要执行不可信代码的场景中。

查看原文 →simonwillison.net