MicroPython в WebAssembly-песочнице: безопасное выполнение Python-кода

Python в песочнице: MicroPython + WebAssembly

Саймон Уиллисон (Simon Willison) — один из создателей Django и автор инструментов Datasette и LLM — годами искал надёжный способ запускать произвольный Python-код в изолированной среде. В начале июня 2026 года он опубликовал статью, в которой рассказал о своём наиболее перспективном решении на сегодняшний день: библиотеке micropython-wasm, сочетающей MicroPython (облегчённая реализация Python) и WebAssembly (WASM — бинарный формат для безопасного выполнения кода).

«Кажется, наконец-то я нашёл решение для Python-песочницы, которое отвечает всем моим требованиям.»


Зачем вообще нужна песочница?

Уиллисон активно развивает плагинную архитектуру во всех своих ключевых проектах — Datasette, LLM и sqlite-utils. Плагины — мощный механизм расширения функциональности: новую возможность можно добавить буквально за ночь, не затрагивая ядро приложения. Однако у такого подхода есть принципиальная проблема.

Все его плагинные системы используют Python и библиотеку Pluggy, а значит, код плагина исполняется с полными привилегиями внутри приложения. Если плагин содержит ошибку или вредоносный код, последствия могут быть непредсказуемыми. Это особенно критично в контексте ИИ-агентов, которые сами генерируют и выполняют код.

⚠ Проблема доверия к плагинам
Когда плагин запускается с правами основного приложения, он получает доступ к файловой системе, сети и всем переменным среды. Один некорректный плагин способен скомпрометировать всю систему.

Что должна уметь идеальная песочница?

Перед тем как выбрать технологию, Уиллисон сформулировал список требований к идеальной изолированной среде выполнения:

ТребованиеОписание
Изоляция файловой системыКод не должен читать или писать файлы без явного разрешения
Отсутствие сетевого доступаНикаких исходящих соединений по умолчанию
Ограничение памятиКонтроль над максимальным объёмом RAM
Ограничение CPUЗащита от бесконечных циклов и зависания
Простота встраиванияДолжно легко подключаться к Python-приложению
Активная поддержкаПроект не должен быть заброшен

Почему WebAssembly?

Веб-браузеры ежедневно скачивают и исполняют недоверенный код с тысяч сайтов — это одна из самых враждебных сред с точки зрения безопасности. JavaScript-движки теоретически могут служить песочницами, но на практике они чрезвычайно сложны в реализации и не предназначены для лёгкого встраивания в сторонние проекты. Большинство проектов по типу «V8 внутри Python» слабо поддерживаются и сами предупреждают о небезопасности при работе с полностью недоверенным кодом.

WebAssembly (WASM) — принципиально иной кандидат. Этот формат изначально создавался с акцентом на безопасность и изоляцию, и уже почти десятилетие тестируется в браузерах по всему миру. Библиотека wasmtime для Python активно поддерживается и поставляется с готовыми бинарными пакетами (binary wheels), что упрощает установку.

ℹ Что такое WASM и WASI?
WebAssembly (WASM) — это компактный бинарный формат с почти нативной производительностью, работающий в изолированной виртуальной машине. WASI (WebAssembly System Interface) — стандартизированный интерфейс, определяющий, как WASM-модули взаимодействуют с операционной системой: с файлами, сетью и т.д. WASI-совместимые среды выполнения позволяют тонко настраивать права доступа.

Однако запустить Python внутри WASM непросто: такие динамические языки, как Python, требуют полноценного интерпретатора, скомпилированного в WebAssembly. Популярная библиотека Pyodide отлично решает эту задачу в браузере, но для серверного Python она не подходит — собрана через Emscripten и работает только в браузере или Node.js.


MicroPython как решение

Вместо Pyodide Уиллисон обратил внимание на MicroPython — компактную реализацию Python 3, изначально созданную для микроконтроллеров. Ключевым открытием стал pull request от Ямамото Такахаши (Yamamoto Takahashi) с экспериментальной поддержкой WASI для unix-порта MicroPython.

Для ускорения прототипирования автор привлёк ИИ-инструменты: GPT-5.5 Pro провёл первичное исследование, а Codex Desktop и GPT-5.5 в режиме high получили задание реализовать решение на основе собранного документа с исследованием. Эксперимент удался — в результате был создан прототип Python-библиотеки, способной выполнять код внутри WebAssembly-песочницы.

💡 Подход с ИИ-ассистентом
Уиллисон использовал связку ИИ-агентов для ускорения разработки: один агент проводил исследование и создавал документ с планом, другой реализовывал код на его основе. Такой конвейер позволил дойти от идеи до рабочего прототипа значительно быстрее обычного.

Архитектура micropython-wasm

Пакет micropython-wasm построен вокруг нескольких ключевых принципов:

  • Используется кастомный WASI-артефакт MicroPython (не Emscripten-сборка для браузера/Node.js)
  • Выполнение через официальный пакет wasmtime для Python
  • Каждый запуск — свежий экземпляр Wasmtime (one-shot execution)
  • Опциональный режим персистентной сессии через фоновый поток
  • Доступ к файловой системе хоста — только явно разрешённые директории в режиме read-only
  • Сетевой доступ полностью отсутствует
  • Настраиваемые лимиты: память, «топливо» (fuel) и тайм-аут по реальному времени

graph TD
    A[Python-приложение хоста] --> B[micropython-wasm]
    B --> C[wasmtime Runtime]
    C --> D[WASM-песочница]
    D --> E[MicroPython интерпретатор]
    E --> F[Пользовательский код]
    B -->|Лимиты| G[Память / CPU fuel / Тайм-аут]
    G --> C
    D -->|Нет доступа| H[Сеть]
    D -->|Read-only опционально| I[Файловая система]

Управление ресурсами

Память ограничивается напрямую через механизм wasmtime. CPU контролируется через концепцию «топлива» (fuel) — счётчика операций WebAssembly. По умолчанию установлено 20 миллионов единиц топлива, хотя сам автор признаёт, что оптимальное значение ещё предстоит уточнить на практике.

from micropython_wasm import run

result = run(
    "print(sum(range(10)))",
    memory_bytes=16 * 1024 * 1024,  # 16 МБ
    fuel=20_000_000,
    wall_timeout_seconds=1.0,
    host_result_bytes=256 * 1024,
)

Персистентные сессии

Одной из сложнейших задач оказалось сохранение состояния интерпретатора между вызовами. WASM-сборка запускает интерпретатор, выполняет код и завершает работу — это хорошо для одноразовых скриптов, но не подходит для ИИ-агентов, которым нужно сохранять переменные и функции между запросами.

Для решения этой проблемы реализованы два режима:

MicroPythonSession — держит MicroPython VM живым в фоновом потоке:

from micropython_wasm import MicroPythonSession

with MicroPythonSession() as session:
    session.run("x = 10")
    session.run("print(x)")  # выведет: 10

MicroPythonReplaySession — не держит фоновый поток; вместо этого перед каждым новым фрагментом кода воспроизводит все предыдущие успешные вызовы, восстанавливая состояние:

from micropython_wasm import MicroPythonReplaySession

session = MicroPythonReplaySession()
session.run("""
import math
def hypotenuse(a, b):
    return math.sqrt(a * a + b * b)
""")
result = session.run("print(hypotenuse(3, 4))")
print(result.stdout)  # 5.0
session.close()

Быстрый старт: попробуйте прямо сейчас

Альфа-версия пакета уже доступна на PyPI. Самый простой способ попробовать — через утилиту uvx без предварительной установки:

# Запустить Hello World
uvx micropython-wasm -c 'print("Hello world")'

# Проверить ограничение по топливу (бесконечный цикл)
uvx micropython-wasm -c 's = ""; while True: s += "longer"'
# Вывод: micropython-wasm: guest exited with code 1
📝 Защита от бесконечных циклов
Вторая команда демонстрирует ключевую возможность: бесконечный цикл автоматически прерывается по исчерпании лимита «топлива». Никаких зависаний хост-процесса.

Чтобы защитить систему от мультиарендных (multi-tenant) рабочих нагрузок с высоким риском, рекомендуется запускать каждое выполнение в отдельном рабочем процессе с ограничениями CPU, памяти и времени на уровне ОС в дополнение к WASM-лимитам.


Сравнение подходов к изоляции Python-кода

ПодходИзоляцияСкорость стартаВстраивание в PythonПоддержка
Docker-контейнерВысокаяСотни мсСложноеОтличная
subprocess + chrootСредняя~10 мсСреднееРучная
Pyodide (браузер)ВысокаяБыстроТолько Node.js/браузерОтличная
micropython-wasmВысокая<1 мсПростое (pip)Активная
V8-in-PythonСредняяБыстроСложноеСлабая

Практическое применение: Datasette Agent

Уиллисон уже применяет micropython-wasm в реальном проекте: плагин datasette-agent-micropython добавляет в Datasette Agent возможность безопасно исполнять Python-код, сгенерированный ИИ-агентом. В качестве дополнительной проверки надёжности он специально «натравил» GPT-5.5 xhigh на попытку вырваться из песочницы — пока безуспешно.

Автор надеется, что этот подход привлечёт внимание компаний с профессиональными командами безопасности и побудит их инвестировать в развитие Python-в-WebAssembly как стандартного метода изоляции, открывая свои решения как open source.


Итог

micropython-wasm — это ещё альфа-версия, но уже сейчас она демонстрирует, что связка MicroPython + WASM может закрыть давно существующий пробел в экосистеме Python: безопасное выполнение недоверенного кода без тяжёлых инфраструктурных зависимостей. Для разработчиков плагинных систем, платформ с AI-агентами и любых приложений, принимающих пользовательский код на исполнение, это направление заслуживает самого пристального внимания.

Ссылки: