Running Python code in a sandbox with MicroPython and WASM

For creators and developers relying on generative AI, the ability to execute arbitrary code safely is a game-changer. It means you can…

By AI Maestro June 6, 2026 5 min read

For creators and developers relying on generative AI, the ability to execute arbitrary code safely is a game-changer. It means you can finally let an agent fetch live data, run complex transformations, or manipulate files without risking a security breach on your local machine. This capability removes the friction of trusting unknown code with your infrastructure.

A safer way to extend software

My core open-source tools, including Datasette, LLM, and sqlite-utils, all rely on a plugin architecture. I am a strong advocate for this approach because it allows features to be added rapidly without compromising the stability of the core application. Even radical ideas can be tested without fear of breaking the main codebase.

However, there is a significant vulnerability in this model. My current plugin systems use Python and Pluggy, which means plugins run with full system privileges. A malicious or buggy plugin could compromise the entire application or leak sensitive user data.

I need a solution where code runs in an isolated environment, unable to access the filesystem, connect to the network, or perform other risky actions. This is particularly relevant for features like Datasette Enrichments, where I want to allow users to write code that transforms data stored in tables. Ideally, I could schedule code to fetch approved JSON, format it, and insert it into a database without exposing the host system.

Defining the requirements

To execute code safely within my own applications, I need a sandbox that meets the following criteria:

  • Dependencies must install cleanly from PyPI, including binary wheels for various platforms. Users should not need to perform extra setup steps.
  • Executed code must be strictly limited by memory and CPU usage. Infinite loops like while True: s += "longer string" must not crash the application.
  • Filesystem access must be either completely disabled or strictly controlled by a whitelist of allowed files.
  • Network access must be mediated through a controlled layer that I fully manage.
  • The solution must support interaction with host functions, allowing me to expose specific platform capabilities to the sandboxed code.
  • The tool must be robust, actively maintained, and well-documented. I have encountered too many projects that are abandoned before they are fully utilised.

Why WebAssembly is the right choice

Web browsers are built to execute untrusted code from the internet on every page load. Given this hostile environment, JavaScript engines are natural candidates for sandboxing. Unfortunately, these engines are incredibly complex and difficult to embed in other projects. Most attempts to run v8 inside Python are poorly maintained and explicitly warned against for untrusted code.

WebAssembly offers a superior alternative. It was designed specifically to meet the requirements I need and has been battle-tested in browsers for nearly a decade. The wasmtime Python library is actively maintained and provides the necessary binary wheels.

Running MicroPython in a sandbox

WebAssembly engines like wasmtime execute WebAssembly binaries. While languages like Rust compile directly to WebAssembly, dynamic languages like Python require a full interpreter at runtime to handle primitives like eval().

Pyodide is an excellent tool for running Python in the browser via WebAssembly, but it does not support server-side Python execution. Recent guidance from October 2024 confirms that Pyodide is restricted to browser or Node.js environments.

I turned my attention to MicroPython. As the documentation states:

MicroPython is a lean and efficient implementation of the Python 3 programming language that includes a small subset of the Python standard library and is optimised to run on microcontrollers and in constrained environments.

WebAssembly feels like the perfect constrained environment for this.

Building the prototype

I asked GPT-5.5 Pro to research the field, which led me to a pull request by Yamamoto Takahashi titled “Experimental WASI support for ports/unix”. I then used this research to generate a script that compiles a custom WebAssembly version of MicroPython.

The most challenging aspect was managing persistent interpreter state. The WebAssembly build we use starts the interpreter, runs the code, and then stops it. This works for one-off scripts, but for my use case, I needed variables and functions to remain in memory across multiple execution calls.

By prompting the AI to run code inside MicroPython that calls a host function to fetch the next block of Python code, we solved the problem. The host function blocks until new code is available, perhaps via a thread with a queue. Inside the WebAssembly environment, the MicroPython interpreter waits for a __session_next__() host function call to retrieve the next line of code, executes it using eval(), and then signals completion via __session_result__.

The result is a library where you can maintain a session and run code iteratively:

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)

Supporting host functions required about 78 lines of C code, which compiles into a 362KB WebAssembly blob. While I am not a C programmer, I had the code reviewed and subjected it to extensive testing.

The safety model relies on the fact that if the C code is flawed, the WebAssembly execution simply fails with an exception. Memory limits are handled directly by wasmtime. CPU limits are managed using wasmtime’s “fuel” concept, though finding the right default value remains a work in progress.

Is it ready for production?

It is somewhat ironic that after complaining about immature sandboxing libraries, I have built my own. I have labelled this release as alpha and am not recommending it for anyone unwilling to accept significant risk.

I have tested it sufficiently to use it myself and have shipped a plugin called datasette-agent-micropython. I have also challenged GPT-5.5 xhigh to break out of the sandbox within that plugin, and it has failed so far. I hope this implementation will demonstrate to companies with professional security teams that this approach is viable for high-stakes problems.

Key takeaways

  • WebAssembly combined with MicroPython provides a robust, embeddable sandbox that solves the security risks of running arbitrary Python code.
  • By using a persistent session model with host functions, developers can maintain state and variables across multiple code execution calls.
  • While the approach is currently an alpha release, early testing suggests it is effective at preventing escape attempts from generative AI agents.
  • This technology enables safe code execution for data transformation and automation tasks without exposing the host application to network or filesystem vulnerabilities.

Stay ahead of AI. Get the most important stories delivered to your inbox — no spam, no noise.

Name
Scroll to Top