用MicroPython和WASM搭建Python代码沙箱,安全运行用户提交的代码

如果你运营一个在线编程教育平台或代码评测系统,一定遇到过这个难题:如何安全地运行用户提交的代码?传统的做法是使用Docker容器,但资源消耗大、启动慢。本文介绍一种更轻量的方案——使用MicroPython和WebAssembly(WASM)搭建Python代码沙箱。

为什么选择WASM沙箱?

与传统Docker方案相比,WASM沙箱有以下优势:

启动速度快:WASM模块可以在毫秒级启动,而Docker容器通常需要秒级。

资源消耗低:WASM运行在浏览器或独立的运行时中,内存占用远低于完整的容器环境。

安全性高:WASM默认运行在沙箱环境中,无法访问文件系统和网络,天然适合运行不受信任的代码。

跨平台:WASM可以在任何支持的运行时中运行,无需考虑操作系统差异。

MicroPython简介

MicroPython是Python 3的精简实现,专门为微控制器和嵌入式环境设计。它保留了Python的核心语法和大部分标准库,但移除了一些重量级模块(如完整的socket库、多线程支持等)。

MicroPython可以编译为WASM,这意味着你可以在浏览器或WASM运行时中执行Python代码,而且不需要安装完整的Python环境。

搭建步骤

步骤一:准备MicroPython WASM版本

首先,你需要获取MicroPython的WASM编译版本。可以从官方仓库下载预编译版本,或自行编译:

# 克隆MicroPython仓库
git clone https://github.com/micropython/micropython.git
cd micropython

# 编译WASM版本
make -C ports/webassembly

步骤二:创建HTML宿主页面

创建一个HTML页面来加载和运行MicroPython WASM:

<!DOCTYPE html>
<html>
<head>
    <title>Python Sandbox</title>
</head>
<body>
    <textarea id="code" rows="10" cols="80">
print("Hello from sandbox!")
for i in range(5):
    print(f"Count: {i}")
    </textarea>
    <br>
    <button onclick="runCode()">Run</button>
    <pre id="output"></pre>

    <script src="micropython.wasm"></script>
    <script>
    async function runCode() {
        const code = document.getElementById('code').value;
        const output = document.getElementById('output');
        
        // 创建独立的MicroPython实例
        const mp = await loadMicroPython();
        
        // 重定向stdout
        let result = '';
        mp.setStdout((data) => {
            result += new TextDecoder().decode(data);
        });
        
        try {
            mp.runPython(code);
            output.textContent = result;
        } catch (e) {
            output.textContent = 'Error: ' + e.message;
        }
    }
    </script>
</body>
</html>

步骤三:添加资源限制

为了防止恶意代码消耗过多资源,需要添加执行时间限制和内存限制:

// 设置执行超时(例如5秒)
const TIMEOUT = 5000;

async function runCodeWithTimeout(code) {
    return Promise.race([
        executePython(code),
        new Promise((_, reject) => 
            setTimeout(() => reject(new Error('Execution timeout')), TIMEOUT)
        )
    ]);
}

步骤四:扩展为服务端方案

如果你需要在服务端运行WASM沙箱,可以使用wasmtime或wasmer运行时:

# 安装wasmtime
curl https://wasmtime.dev/install.sh -sSf | bash

# 运行MicroPython WASM
wasmtime micropython.wasm --dir /tmp

安全注意事项

虽然WASM沙箱天然具有隔离性,但仍需注意以下安全问题:

1. 资源限制:必须设置执行时间和内存使用限制,防止DoS攻击。

2. 输出过滤:过滤用户代码的输出,防止XSS攻击(如果输出显示在网页上)。

3. 文件系统隔离:确保WASM实例无法访问主机文件系统。

4. 网络隔离:默认情况下WASM无法访问网络,但需要确保运行时配置正确。

适用场景

这种方案特别适合以下场景:

在线编程教育平台:学生可以直接在浏览器中运行Python代码

代码评测系统:安全地运行和测试用户提交的代码

交互式文档:在文档中嵌入可运行的Python示例

低代码平台:让用户通过Python脚本自定义业务逻辑

对于站长而言,WASM沙箱提供了一种安全、高效、低成本的方式来运行不受信任的代码。如果你的网站需要这个功能,不妨试试MicroPython + WASM的方案。

本文参考来源:Simon Willison: Running Python in a WASM sandbox with MicroPython

© 版权声明
THE END
喜欢就支持一下吧
点赞7 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容