Skip to content

DEF CON 34 talks are here: 354 talks, summarized and searchable.

Browse DEF CON 34

WASM Was Not the Boundary - Sandcastles, Not Sandboxes

Vladimir TokarevSaar Pear

Where

Main Stage
DEF CON 34

Duration

40 min

Shows how untrusted Python running in a Pyodide WebAssembly sandbox escapes into Node.js or Deno host runtimes through ctypes and reflection.

Summary

This talk examines Pyodide, a CPython interpreter compiled to WebAssembly with Emscripten, which several products use as a sandbox for running untrusted Python. The presenters tested seven products spanning workflow automation, spreadsheets, AI agent frameworks, CI build tooling, and desktop wrappers. In most of them, denylists blocked modules such as os and subprocess, but ctypes stayed importable, and class-hierarchy traversal could recover an import function even when it was not.

With ctypes, the escaped code can load the Emscripten exports of the process, pull out functions that run scripts, declare their signatures, and execute JavaScript on the host. On Node.js this gives immediate code execution. On Deno the outcome depends on the granted permissions, and one default configuration still reached full remote code execution. In CI, the escaped code runs beside tokens, signing keys, and release artifacts. The team reported seven escapes and four CVEs, and vendor responses varied, from archiving projects to calling the issue the deployer's responsibility.

The main takeaway is that denylists fail at the architectural level. The presenters recommended blocking ctypes at import, compiling out script-running exports, blocking reflection gadgets, and exporting only the functions an application needs. They also advised layering permissions and containers, and checking whether ctypes is importable, which host runtime is used, and which permissions are granted.

Materials

Related talks