Datasette・LLMなどのオープンソースツール作者として知られるSimon Willisonが、MicroPythonをWebAssembly(WASM)上で動作させてPythonコードを安全に隔離実行するアルファ版パッケージ「micropython-wasm」をPyPIで公開した。AIエージェントが動的にコードを生成・実行するユースケースが急増する中、安全なサンドボックス実行の重要性が改めて問われている。
なぜサンドボックスが必要なのか
Willisonのプロジェクト群——Datasette、LLM、sqlite-utils——はいずれもプラグインシステムを持ち、PythonのPluggyを使って拡張できる設計になっている。しかし現状では、プラグインのコードはアプリケーション内でフル権限で実行される。悪意あるプラグインや不具合のあるコードがファイルを読み取ったりネットワークに接続したりするリスクを排除できない。
さらに、LLMが生成したコードをそのままホストで実行する「datasette-agent-micropython」のようなユースケースでは、適切な隔離なしの実行は明らかに危険だ。
WebAssemblyを選んだ理由
候補として検討されたのは次のアプローチだ:
- V8(JavaScriptエンジン)のPython組み込み: メンテナンスが散漫なプロジェクトが多く、完全に信頼できないコードへの使用は非推奨とされるものがほとんど
- WebAssembly(WASM): ブラウザがほぼ10年にわたって悪意あるコードを安全に実行するために磨き上げてきた仕組み。
wasmtimeパッケージはアクティブにメンテナンスされ、バイナリwheelも提供されている
WebAssemblyはセキュリティモデルを中心に設計されており、メモリ・CPU・ファイルシステム・ネットワークへのアクセスをホスト側が精密に制御できる点が決め手となった。
MicroPythonをWASMで動かす
WebAssembly上でPythonを実行するには、Pythonインタープリタ自体をWASMにコンパイルする必要がある。よく知られたPyodideはブラウザやNode.js専用であり、サーバーサイドのPythonからは使えない。
そこでWillisonが目を向けたのがMicroPythonだ。マイコン向けに設計された軽量Python実装で、「制約された環境での動作」を前提としている点がWASMと相性が良い。MicroPythonコミュニティによる「WASIサポートの実験的PR」の発見が突破口となった。
実装の工夫:永続的なインタープリタ状態
最大の課題はセッション間での変数の保持だった。WASMビルドの素朴な実装では、コードを実行するたびにインタープリタが起動・終了してしまう。
解決策として採用したのがスレッド+キュー方式だ:
- バックグラウンドスレッドでWASM上のMicroPythonインタープリタを起動し続ける
- ホスト側の
__session_next__()関数からコードを受け取り、eval()で実行 - 実行結果をリプライキューで返す
これにより、複数のsession.run()呼び出し間で変数状態が保持される:
出典: この記事は Running Python code in a sandbox with MicroPython and WASM の内容をもとに、筆者の見解を加えて独自に執筆したものです。