Running Python code in a sandbox with MicroPython and WASM
Simon Willison ยท email ยท 2026-06-06 Reader ๐ฅ๏ธ
WebAssembly-embedded MicroPython is the first Python sandbox that meets all the criteria Willison thinks a trustworthy in-process sandbox must satisfy โ clean PyPI install, memory/CPU limits, controlled file and network access, host-function interop, and active upstream maintenance โ making it the right substrate for safely running plugin and agent-generated Python code.
practical ยท mixed โ Lead piece is a practical/expository build log with embedded argument about sandbox requirements. The newsletter wrapper bolts on a roundup of links and quotes; through-line is sandboxing-for-agent-executed-code.
Structure
| Part | Role |
|---|---|
| Motivation: plugin systems and agent-generated code both need a way to run untrusted Python without full host privileges | context โ establishes the problem the sandbox is meant to solve |
| Requirements list: six criteria a usable sandbox must meet (install, memory, CPU, files, network, host functions, maintenance) | evaluative framework โ sets the bar against which all candidates are judged |
| Survey of alternatives: JavaScript engines too complex; Pyodide browser-only; MicroPython designed for constrained environments | evidence by elimination โ narrows the space to MicroPython+WASM |
| Build log: using GPT-5.5 Pro and Codex to compile MicroPython to WASM, solve persistent interpreter state via a queue/eval loop, expose host functions in 78 lines of C | existence proof โ shows the approach is viable |
| Trust caveat: 'should you trust my vibe-coded sandbox?' โ alpha, irony acknowledged, hopes professional security teams will adopt the approach | honest scoping โ bounds the claim being made |
| Roundup items: Anthropic's containment doc, OpenAI Lockdown Mode, Meta AI account-takeover failure, Uber AI spend caps, Charity Majors enthusiasts-vs-skeptics | ambient reinforcement โ most touch sandboxing, exfiltration, or agent-spend governance |
Key terms
- sandbox Sandboxing
An in-process execution environment for untrusted code that enforces memory/CPU limits, mediates all file and network access, and lets the host selectively expose functions โ embeddable as a Python package - vibe-coded Vibe Coding
Built primarily via prompting coding agents (here Codex Desktop + GPT-5.5) with the human reviewing rather than authoring; used self-deprecatingly when applied to security-critical code - fuel
wasmtime's unit for bounding WebAssembly compute; Willison uses it as his CPU limit but is unsure 20M is the right default - Lethal Trifecta Lethal Trifecta
His prior framing (invoked in the Lockdown Mode item): private data + untrusted content + exfiltration channel; cut any one leg to neutralize prompt-injection risk - host functions
Functions defined in the outer Python application that sandboxed MicroPython code may call โ the controlled interface through which all privileged operations must pass
Propositions
- explicitA plugin system that grants full host privileges to plugin code is structurally unsafe.conf: highextendsIncident 1368: Malicious OpenClaw Skills Reportedly Delivered AMOS Stealer and Exfiltrated Credentials via ClawHub ยท p5 โ Locates the deeper structural cause behind the vetting gap: plugin/skill code granted full host privileges is unsafe regardless of how well submissions are vetted.
- explicitWebAssembly is a better sandbox substrate than embedded JavaScript engines because it was designed for hostile execution and has actively maintained Python bindings (wasmtime).conf: high
- explicitMicroPython, originally targeting microcontrollers, fits WebAssembly's resource constraints better than CPython-derived runtimes like Pyodide for server-side embedding.conf: high
- explicitSandboxes without active maintenance and clear documentation should not be trusted, regardless of their technical design.conf: high
- implicitCoding agents make it economically reasonable for a single developer to build infrastructure that previously required a team โ including a custom Python interpreter integration.conf: highextendsEight years of wanting, three months of building with AI ยท p2 โ Willison generalizes the observation that AI changed what a solo project could be: coding agents make it economical for one developer to build infrastructure that previously required a team.
- explicitcorroboratedCutting the exfiltration leg is the highest-leverage defense against prompt injection because the other two legs (private data, untrusted content) are difficult to remove without crippling utility.conf: highrefines11) AI-spesial med Vilde Opsal og Anders Sveen ยท p16 โ Accepts that prompt injection is intrinsic and specifies the highest-leverage mitigation: cut the exfiltration leg of the lethal trifecta.refinesHow GitHub Is Securing Agentic Workflows in Modern CI CD Systems ยท p8 โ Narrows the isolation claim: network containment matters specifically because cutting the exfiltration leg of the lethal trifecta is the highest-leverage defense, not because isolation is broadly sufficient.supports โGitLost: How We Tricked GitHub's AI Agent into Leaking Private Repos ยท p7 โ Noma's recommendation to 'restrict what any agent can post publicly' is the same highest-leverage remedy Willison identifies โ cutting the exfiltration-channel leg of the lethal trifecta โ applied here to a public issue-comment channel rather than network egress.extends โPrompt Injection to Data Exfil in 3 Hops ยท p10 โ Operationalizes Willison's 'cutting the exfiltration leg is the highest-leverage defense' as a concrete network-egress control, while qualifying that the channel can only be contained deterministically, not removed.
- implicitThe right unit of safety for agent-generated code is the execution boundary, not the model's intentions or correctness.conf: high
- implicitcorroboratedSandboxing only bounds blast radius; it does not prevent agents from executing wrong-but-sanctioned code within the sandbox.conf: highrefinesHow OpenAI Built a Secure Windows Sandbox for Codex Agents ยท p7 โ Adds the limit condition to OS-level containment: sandboxing bounds blast radius but cannot stop wrong-but-sanctioned actions executed inside the granted scope.supports โPresentation: Fixing the AI Infra Scale Problem by Stuffing 1M Sandboxes in a Single Server ยท p11 โ The credential-proxy answer illustrates exactly Willison's point that sandboxing bounds blast radius but doesn't prevent agents from misusing sanctioned power (e.g. a leaked credential) within the sandbox โ hence keeping credentials outside the sandbox entirely.
- explicitSelf-built sandboxes from non-security specialists are inadequate for high-stakes deployments; institutional adopters with professional security teams are needed.conf: high
Arguments
MicroPython+WASM is the right substrate for a Python sandbox embeddable in Python applications. strength: high
Explicit premises:
- A trustworthy sandbox must satisfy six criteria (clean install, memory limits, CPU limits, file mediation, network mediation, host functions, active maintenance).
- JavaScript-engine embeds for Python are poorly maintained and warn against untrusted input.
- Pyodide is browser/Node only and not supported server-side.
- MicroPython is designed for constrained environments and compiles to WebAssembly via WASI.
- wasmtime provides memory limits natively and a fuel mechanism for CPU bounding.
Implicit premises:
- The six criteria are jointly sufficient, not merely necessary, for a sandbox to be trustworthy.
- Bounding blast radius is the safety property that matters most for plugin/agent-executed code.
- MicroPython's smaller standard library is acceptable for the workloads Willison cares about (Datasette enrichments, plugin glue, agent-generated data shaping).
Inferences:
- If MicroPython+WASM meets the criteria, every comparable substrate (Lua-in-WASM, QuickJS, gVisor for in-process Python) should be evaluated against the same six-point rubric.
- Sandbox maturity is bottlenecked on documentation and institutional adoption more than on technical novelty.
It's defensible to ship an alpha sandbox built largely with coding agents because the WASM boundary contains failures. strength: medium
Explicit premises:
- If the C code has bugs, the worst outcome is a WASM exception, not host compromise.
- Two LLMs have explained the code to Willison and it has been tested.
- GPT-5.5 xhigh has been challenged to break out and has not.
Implicit premises:
- wasmtime itself is trustworthy enough that its boundary will hold even when the in-sandbox C is wrong.
- Adversarial testing by a frontier model is a meaningful proxy for adversarial testing by humans + automated tools.
- Risk from a buggy sandbox is borne by the operator who chose to install it, not by third parties.
Inferences:
- The argument transfers cleanly to anyone building sandbox tooling on top of mature isolation primitives: the substrate carries most of the safety budget.
- If the substrate ever fails, all of the downstream 'vibe-coded' sandboxes inherit a coordinated vulnerability.
Cutting exfiltration is the right industry-wide defense posture for LLM systems exposed to untrusted content. strength: high
Explicit premises:
- The Lethal Trifecta requires all three legs; removing any one neutralizes it.
- Private data access and untrusted-content exposure are hard to remove without making products useless.
- Deterministic egress controls (Lockdown Mode, sandbox network mediation) are not subvertable by prompt injection.
Implicit premises:
- Most damaging outcomes require exfiltration; in-place damage (corruption, denial of service inside the sandbox) is tolerable.
- Egress channels are enumerable and closeable โ the API surface is small enough to lock down.
Inferences:
- Default-on egress restriction should become baseline product behavior; the existence of Lockdown Mode as opt-in is itself an admission that defaults are inadequate.
- Sandboxes that meet Willison's network criterion are doing the same work as Lockdown Mode at a finer grain.
Narratives
- Willison prompts Codex with 'read research.md and build this' โ it produces a working WASM build script and a prototype that executes Python in a sandbox.
โ Shows that the proposition 'coding agents make sandbox infrastructure economically viable for a solo developer' is concretely true. - Persistent-state design conversation: Willison floats a queue+eval scheme, the agent iterates with him to a working session abstraction.
โ Models the human-as-architect / agent-as-implementer pattern he advocates throughout his writing. - Meta wired its support bot to perform account recovery and attackers just asked it to relink the email.
โ Implicit support for the unity: even when sandboxing is the conversation, the simpler failure mode is granting the agent excessive sanctioned authority โ the sandbox cannot save you if the agent's mandated actions are themselves catastrophic. - Uber caps each engineer at $1,500/month per AI coding tool โ Willison computes this is ~11% of median compensation.
โ Narrative anchor for the larger ambient argument that the industry is now negotiating real economic and governance limits on agent execution, of which sandboxing is one axis. - Chad Whitacre publicly retires from tech and goes 'AI Amish' over the agentic Kool-Aid; David Wilson lists 16 abandoned projects and recommends discipline; Charity Majors describes enthusiasts vs. skeptics as both right.
โ Roundup chorus โ the cost side of the ledger Willison's lead piece doesn't engage. The sandbox solves the safety question and silently brackets the discipline question.
Questions addressed
- โ
What does a sandbox need to support to be trustworthy enough to embed in a real Python application?
Six explicit criteria: PyPI-installable, memory limits, CPU limits, file mediation, network mediation, host functions, active maintenance. - โ
Can a single developer, working with coding agents, produce a viable Python-in-WASM sandbox?
Yes โ micropython-wasm 0.1a0 exists, with persistent sessions and host-function interop in 78 lines of C. - โ
Should you trust this specific implementation in production?
No โ alpha, recommended only for users willing to take significant risk; hopes professional security teams will pick up the approach. - โญ Does sandboxing solve the problem of agents executing destructive code, or only bound its reach?
Not addressed โ Willison's framing equates 'cannot escape' with 'safe', collapsing sanctioned-but-wrong actions into background noise. - โญ What's the right CPU bound (fuel value) for general-purpose sandboxed Python?
Explicitly open โ 20M is a guess; units 'are hard to reason about'. - โญ How should an organization manage proliferation of cheap-to-build, easy-to-abandon AI-generated projects?
Raised in the roundup (David Wilson, Charity Majors) but not connected to the sandbox piece, even though the sandbox makes proliferation easier.
Gaps
- incompleteNo explicit threat model. The article enumerates sandbox capabilities but never names the adversary: is it a confused agent, a malicious plugin author, a prompt-injection chain, or a curious user? Each implies different controls and different acceptable risk.
Read next: Anthropic's 'How we contain Claude' (linked in the same newsletter) provides an explicit threat-model decomposition; pair with Willison's earlier Lethal Trifecta essay for an integrated view. - incompleteSandboxing solves blast-radius questions but not authority questions. The Meta example (linked in the same issue) shows that the catastrophic failure is granting agents excessive *sanctioned* power โ which a perfectly secure sandbox does nothing to prevent. The article never connects these.
Read next: Read the Meta item against Anthropic containment essay against this piece syntopically; ask 'what authority does the code inside the sandbox have, and who decided?' - incompletePyodide is dismissed for server-side use on the basis of a 2024 statement; no engagement with running Pyodide via Node embeddings, with PyPy-WASM, RustPython, Starlark, or restricted-Python variants. The 'survey of alternatives' is thin given the strength of the resulting claim.
Read next: Recent Pyodide release notes, RustPython status, the Bytecode Alliance's component-model work for cross-language sandboxing. - incompleteNo discussion of side channels or supply-chain risk in the distributed 362KB WASM blob. A prebuilt opaque artifact in a PyPI package is itself a trust delegation, and reproducible builds are not addressed.
Read next: WebAssembly component-model security analyses; reproducible-build practices for prebuilt native artifacts on PyPI. - incompleteThe cost/discipline thread (Whitacre, Wilson, Majors, Uber caps) is present in the newsletter but disconnected from the lead piece. Willison's sandbox lowers the cost of spinning up agent-executed code; the roundup says that's already the bottleneck. The unity does not acknowledge that making sandboxed execution cheaper might make the discipline problem worse.
Read next: Majors's enthusiasts/skeptics piece; David Wilson's 'cancelling my AI subscription'; treat them as a counterweight when evaluating sandbox-as-enabler.closed byErik van der Pluijm's Post โ This post is an empirical instance of the exact concern that gap raised (cheaper building makes the discipline problem worse, not better) and supplies the team-level response the earlier material lacked: drop effort metrics, keep a recurring explicit value/ship judgment as the discipline mechanism.
Closes gaps elsewhere
- 11) AI-spesial med Vilde Opsal og Anders Sveen ยท g5 โ Willison offers a concrete next sandbox abstraction beyond staged-autonomy stopgaps: a WASM/MicroPython execution boundary as the unit of safety for agent-generated code, with blast-radius containment rather than trust in model intentions.
- Hacking Meta's AI Chatbot ยท g3 โ Tests the 'no class-level defense' assertion: cutting the exfiltration leg and enforcing safety at the execution boundary are class-level architectural defenses that work regardless of what the LLM is convinced to say.
- Trust Factory ยท g2 โ Willison provides the missing treatment of misplaced trust: do not trust agent code at all โ contain it at an execution boundary and cut the exfiltration leg, since sandboxing (not trust) is the answer to prompt-injected or wrong-but-sanctioned actions.
Related documents
- Incident 1368: Malicious OpenClaw Skills Reportedly Delivered AMOS Stealer and Exfiltrated Credentials via ClawHub
- Anthropic Details How It Contains Claude Across Web, Code, and Cowork
- The Claude Code active attack didn't stop. 294,842 secrets stolen from 6,943 machines. It evolved and now spreads through Python too and uses Claude Code itself to steal your secrets. The risk to your credentials just got bigger.
- GitLab Warns That AI Agent Sandboxes Are Only as Secure as Their Network Access
- 11) AI-spesial med Vilde Opsal og Anders Sveen
- Vibe Coding Agent Security And Evaluation
- How OpenAI Built a Secure Windows Sandbox for Codex Agents
- A big week for AI denialism
- Agentic AI and Code Reviews
- AWS MCP Server Reaches GA with Full API Coverage and IAM-Based Governance