Безопасный запуск кода AI-агентов: как устроены быстрые песочницы
AI-агент хочет запустить сгенерированный код. Docker небезопасен, классическая VM медленная. Zeroboot поднимает KVM-песочницу за менее чем 1 мс через CoW-снимки. Разбираю механику.
Мой AI-агент написал скрипт на Python и попросил его выполнить. Безобидный анализ CSV-файла — три строки кода. Я глянул мельком, нажал «запустить». Скрипт отработал, вернул результат.
Через неделю другой агент, другая задача. Скрипт выглядел нормально, но внутри — subprocess.Popen с вызовом curl на внешний URL. Агент не злонамеренный: он решил скачать библиотеку, которой не хватало. Но если бы в переменных окружения лежали API-ключи — curl мог отправить их куда угодно.
Это момент, когда понимаешь: AI-агент, выполняющий произвольный код на твоей машине, — контролируемый взрыв. Нужна камера, которая выдержит. Не Docker — он тоньше, чем кажется. Нужна полноценная виртуальная машина. И она должна стартовать мгновенно.
Почему контейнер — не стена
Docker изолирует через Linux namespaces и cgroups. Процесс внутри контейнера видит своё PID-пространство, свою файловую систему, свою сеть. Выглядит изолированно. Но:
Ядро — общее. Контейнер и хост делят один Linux kernel. Каждый системный вызов из контейнера обрабатывается ядром хоста. Уязвимость в ядре — выход наружу.
Поверхность атаки — 300+ syscalls. Контейнерный процесс может вызывать сотни системных вызовов к ядру хоста. Seccomp-профиль фильтрует самые опасные, но default Docker profile блокирует лишь ~44 из ~330.
Misconfiguration = полный доступ. --privileged флаг, монтирование Docker socket, capabilities вроде SYS_ADMIN — и контейнер становится root на хосте.
Для предсказуемого кода Docker достаточен. Для произвольного кода, сгенерированного LLM, — нет.
Виртуальная машина: правильная граница
KVM-виртуалка — другой уровень. Собственное ядро, собственная память, аппаратная изоляция через Intel VT-x / AMD-V. Проблема: скорость запуска. Docker: 50-300 мс. QEMU/KVM: 1-5 секунд. Для интерактивного агента в цикле итераций — каждые 300 мс ощутимы.
Zeroboot: не запускать — восстанавливать
Классический старт VM: BIOS → загрузчик → ядро → init → сервисы → готова. Идея Zeroboot: зачем загружать с нуля, если можно восстановить готовое?
Фаза 1 (один раз): загрузить VM полностью, установить Python + библиотеки + agent helper, сделать snapshot (дамп RAM + CPU + devices).
Фаза 2 (каждый раз): mmap(snapshot.mem, MAP_PRIVATE) за 0.3-0.5 мс + restore регистров за 0.1-0.2 мс + resume. Итого менее 1 мс.
mmap с MAP_PRIVATE — ключ. Не копирует данные (demand paging — загрузка по page fault). Copy-on-write: чтение из общего файла, запись создаёт приватную копию. 20 параллельных VM из одного snapshot: 2 GB shared + ~50 MB × 20 private ≈ 3 GB вместо 40 GB.
Практическая архитектура
Пул прогретых VM (15 штук). VM одноразовые — после выполнения уничтожаются. Коммуникация через vsock (прямой канал хост-VM, латентность — десятки микросекунд). Двухуровневые лимиты: на гипервизоре (1 vCPU, 512 MB RAM, deny_all сеть) и внутри VM (rlimit).
Сравнение подходов
Docker: 50-300 мс, namespaces изоляция, бесплатно.
gVisor: 100-400 мс, user-space ядро, бесплатно.
Firecracker: 125-300 мс, KVM изоляция, ~$50/мес self-hosted.
Snapshot VM: менее 1 мс, KVM изоляция, ~$50/мес self-hosted, сложнее в управлении.
Когда что выбирать
Прототип — E2B или Docker. Production — Firecracker. Интерактивный агент в цикле — Snapshot VM. High-throughput — Snapshot VM с пулом (CoW sharing снижает RAM в 5-10 раз).
Быстрые песочницы — фундаментальная инфраструктура для AI-агентов, которые делают что-то полезное. mmap, MAP_PRIVATE, demand paging, copy-on-write — технологии из 1990-х. Новое — не механизм, а его применение: дать AI-агенту собственную машину за миллисекунду.