惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
Vulnerabilities – Threatpost
aimingoo的专栏
aimingoo的专栏
B
Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
GbyAI
GbyAI
阮一峰的网络日志
阮一峰的网络日志
Engineering at Meta
Engineering at Meta
IT之家
IT之家
V
Visual Studio Blog
The Cloudflare Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
A
About on SuperTechFans
博客园 - 聂微东
Blog — PlanetScale
Blog — PlanetScale
N
News and Events Feed by Topic
A
Arctic Wolf
WordPress大学
WordPress大学
小众软件
小众软件
C
CERT Recently Published Vulnerability Notes
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
D
Darknet – Hacking Tools, Hacker News & Cyber Security
F
Fortinet All Blogs
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Y
Y Combinator Blog
T
Threat Research - Cisco Blogs
Latest news
Latest news
Simon Willison's Weblog
Simon Willison's Weblog
Cyberwarzone
Cyberwarzone
S
Schneier on Security
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
L
Lohrmann on Cybersecurity
Stack Overflow Blog
Stack Overflow Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
P
Privacy International News Feed
J
Java Code Geeks
Spread Privacy
Spread Privacy
宝玉的分享
宝玉的分享
I
Intezer
L
LangChain Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
G
GRAHAM CLULEY
博客园 - 叶小钗
博客园 - 三生石上(FineUI控件)
The GitHub Blog
The GitHub Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
N
News and Events Feed by Topic
AWS News Blog
AWS News Blog
Attack and Defense Labs
Attack and Defense Labs
Security Archives - TechRepublic
Security Archives - TechRepublic
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Полезайте в песочницу, мистер Claude: изолируем агента
Andrew42 · 2026-06-24 · via Все публикации подряд на Хабре

Всем привет!

Это Андрей Яковлев, исследователь в области кибербезопасности. Сегодня разбираем, как изолировать ИИ-агент в виртуальной среде с помощью Docker Sandbox.

У меня в ~/.config/secretkeys/ лежит очень важный OAuth-токен. У вас на машине, скорее всего, тоже есть аналогичные штуки: ключи от облака, GitHub PAT в ~/.config/gh/, SSH-ключи в ~/.ssh/. И когда ИИ-агент запущен от имени моего пользователя, он видит все это по тем же путям, что и я. Не гипотетически может увидеть, а буквально читает и может распорядиться властью, данной ему, не самым лучшим образом, о чем я рассказывал в предыдущей статье. Поэтому я долго не пользовался агентами всерьез.

Больше всего меня пугали не риски промпт-инъекции или намеренной атаки. Давила постоянная тревожность: запущу агент не в той директории, а он перепутает токены и сходит туда, куда не надо, либо снесет диск одной командой. Я делал отдельные виртуалки под каждый проект и они работали, но ели время и ресурсы. Хотелось иметь инструмент, которому можно доверять и который не потребует ставить дома серверную стойку под вычислительные ресурсы для виртуальных машин.

Несколько месяцев назад я нашел инструмент, который, как мне тогда показалось, отлично подойдет под мои запросы. Разбираю, что из этого вышло.

Содержание

Уточнение терминов

Архитектура изоляции

Установка

Основные команды

Сетевые политики

--dangerously-skip-permissions

Секреты

Что закрывает изоляция

Куда дальше

В предыдущей статье я разбирал шесть классов угроз для кодовых ИИ-агентов: случайный rm -rf, промпт-инъекцию, малварь, использующую агент как инструмент разведки, атаку на цепочку поставок через установку стороннего пакета, кражу токенов доступа и каскадную CI/CD-компрометацию. Общий знаменатель здесь — процесс агента, имеющего полные права того пользователя, который его запустил. Сейчас изоляция на уровне среды представляется не просто прогрессивным инструментом безопасности, а обязательным условием использования агента.

Эта статья про то, как и с помощью чего собирается изоляция, без глубокого технического разбора виртуализации и без воспроизведения атак на практике; этот материал я оставлю для следующих заходов. Конкретно я рассматриваю инструмент от Docker под названием Docker Sandbox — микровиртуалку с собственным ядром, сетью с файрволом «из коробки» и приватным Docker-демоном. Docker Sandbox ставится в три команды и заменяет отдельные виртуальные машины (далее — VM), созданные вручную под каждый проект с агентом.

Сразу скажу про источники информации для статьи: это официальная документация Docker по sandbox (на момент написания полная), включая архитектурный раздел и Network Policies. Я опираюсь на нее и размещаю рядом свой опыт, который накопил за несколько месяцев ежедневного использования агентов с Docker Sandbox. Если что-то в тексте у меня не совпадает с документацией, я опираюсь на практику. Где это важно, оговариваюсь явно.

Инструмент активно развивается: к примеру, за несколько месяцев успела появиться и устареть версия, включаемая в Docker Desktop, а официальная документация на сайте Docker несколько раз переписывалась. То есть на момент вашего, дорогой читатель, знакомства со статьей некоторые детали могут отличаться от описанных ниже. Поэтому настоятельно рекомендую сверяться с актуальной версией документации на официальном сайте Docker [1] перед началом использования.

Уточнение терминов

Прежде чем перейти к командам, определим терминологию. Под Docker Sandbox я понимаю продукт в целом: концепцию microVM-изоляции для ИИ-агентов от Docker. sbx — это CLI-инструмент, через который продукт сейчас живет. Раньше у Docker была другая имплементация в виде команды docker sandbox в Docker Desktop, с нее все начиналось. Но в актуальной документации она помечена как устаревшая и заменена на отдельный CLI-инструмент sbx. Дальше в статье я говорю про sbx.

Архитектура изоляции

В этом разделе приведу пять утверждений, которых хватит, чтобы понять, что именно дает изоляция и где заканчиваются ее границы.

Контейнер делит ядро с хостом, а sandbox нет

Контейнер — это набор специфичных для Linux механизмов: namespaces изолируют процессы и сеть, cgroups ограничивают ресурсы. Но ядро у контейнера и у хоста общее, поэтому любой системный вызов из контейнера проходит через то же ядро, что и системные вызовы пользователя. Sandbox устроен иначе: он запускается как отдельная microVM с собственным ядром, а границей между агентом и хостом выступает гипервизор, а не namespaces [2]. Это принципиально другой уровень изоляции.

Агент не видит ваш Docker

Внутри microVM работает собственный Docker-демон. Агент может собирать образы, запускать контейнеры, поднимать docker-compose, и ничего из этого не доходит до хостового Docker Engine. Сокет хоста (/var/run/docker.sock) недоступен для монтирования внутрь sandbox [3]. Это снимает целый класс эскалаций, где потенциальная вредоносная нагрузка дотягивается до Docker socket и через него управляет хостом. [Docker Security Cheat Sheet]

Агент не видит ваши файлы — кроме тех, что вы сами показали

В sandbox видна только рабочая директория (workspace в терминологии Docker), которую вы передали при sbx run. Другие директории хоста — ~/.ssh/, ~/.config/cloud/, /etc/ — недоступны фундаментально [2]. Символическая ссылка за пределы области не разрешается [2]. Важная оговорка: если вы передаете домашнюю директорию целиком (sbx run claude ~), агент получает доступ ко всему, что лежит в домашнем каталоге, в том числе к ключам. Естественно, это ожидаемое поведение, так и задумано, поэтому рабочую директорию агента стоит ограничивать минимально необходимым.

Sandbox живет между запусками, в отличие от обычного контейнера

Привычный контейнер одноразовый: упал, перезапустил и состояние стерто.

Да, можно ставить контейнер на паузу и хранить состояние во внешних каталогах, которые будут монтироваться каждый раз. Но это не совсем оно.

Sandbox устроен иначе. Пакеты, конфиги и скилы агента остаются между запусками, пока вы не сделаете sbx rm. У меня скилы лежат в двух местах: частично в ~/.claude внутри sandbox (живут с конкретным sandbox), частично — в репозитории проекта (живут с кодом и попадают внутрь sandbox вместе с рабочей директорией). Второй паттерн устойчивее: репозиторий переносится между sandbox, скилы переезжают вместе с кодом.

Сеть через прокси на вашем хосте

Из sandbox наружу идет только HTTP/HTTPS [5] и только через прокси на стороне хоста (host-side proxy в документации Docker [5]). Просто TCP, UDP, ICMP, DNS заблокированы на сетевом уровне [5]. Прокси делает TLS-терминацию и заодно инжектирует заголовки авторизации из ваших секретов, которые лежат вне sandbox, так что настоящее значение API-ключа в sandbox вообще не попадает. Заодно блокируются обращения к private IP, loopback и link-local [5].

Итог: изнутри Sandbox трафик идет наружу через локальный MITM прокси на хосте, все остальное на сетевом уровне отрезано.

Граница изоляции понятна. Издержки изоляции — это следующий вопрос.

Установка

Перед установкой Docker sbx стоит учесть два момента.

Первый: согласно документации Docker, на момент написания статьи поддерживаются macOS Sonoma 14 и новее, Windows 11, а также Ubuntu 24.04 и новее с поддержкой KVM.[4]. Несколько месяцев назад картина была другая: когда я ставил sbx в macOS в феврале 2026-го, требовалась именно Tahoe (версия 26). Пришлось обновляться с Sequoia.

Второй: команды установки на разных платформах разные. В macOS через Homebrew, в Windows через winget, в Linux — через apt. Это видно в блоках ниже. А вот команды самого sbx после установки везде одинаковые: sbx run, sbx ls, sbx policy работают на любой ОС без модификаций. Дальше в статье приведены команды установки для каждой платформы отдельно, а примеры запуска и настройки без разделения, потому что они идентичны для всех платформ.

# macOS
brew install docker/tap/sbx
sbx login
# Windows
winget install -h Docker.sbx
sbx login
# Linux (Ubuntu)
curl -fsSL https://get.docker.com | sudo REPO_ONLY=1 sh
sudo apt-get install docker-sbx
sudo usermod -aG kvm $USER
newgrp kvm
sbx login

На Linux чуть больше шагов. Сначала подключается APT-репозиторий Docker (флаг REPO_ONLY=1 ставит только репозиторий, без самого Docker Engine). Потом из него ставится пакет docker-sbx, и ваш пользователь добавляется в группу kvm. sbx использует KVM как гипервизор, и без доступа к нему microVM не поднимется.

Если что-то пошло не так, sbx diagnose покажет, где именно. Команда проверяет бинарь CLI, daemon, версии, состояние директорий и аутентификации, умеет выводить данные в JSON и в Markdown для репорта в issue Docker.

sbx login запускает OAuth в браузере и записывает сессию локально. Да, и мне не до конца понятно, зачем логиниться. Докер объясняет это довольно пространными формулировками о необходимости идентификации и удобстве управления политиками внутри команды. После авторизации CLI просит выбрать сетевую политику по умолчанию: это часть онбординга и необходимый шаг [4]. О пресетах политики я расскажу ниже в отдельном разделе.

Выбор сетевой политики при первом sbx login. Три варианта (Open, Balanced, Locked Down). Базового варианта из коробки нет, осознанный выбор обязателен.

Выбор сетевой политики при первом sbx login. Три варианта (Open, Balanced, Locked Down). Базового варианта из коробки нет, осознанный выбор обязателен.

Docker Desktop при работе с sbx не нужен. Управление политиками на уровне организации возможно, но это отдельный платный продукт Docker AI Governance, подробнее о нем я рассказываю в разделе «Сетевые политики». Без подписки на Docker AI Governance sbx работает локально, без ограничений администратора. Это нормальный режим для индивидуального разработчика.

CLI поставлен. Что с ним реально делают каждый день?

Основные команды

Сценарий, который я демонстрирую, простой: создаем sandbox, запускаем агент, заходим в shell параллельно. Один сплошной фрагмент, как это выглядит у меня в реальности:

████████  ~  ♥️ 13:18  cd ~/myProject
████████  myProject  ♥️ 13:19  sbx run claude
Creating new sandbox 'claude-myProject'...
a8531b2e5fc6: Download complete
0e4f92455740: Download complete
c2407f5c2e01: Download complete
2417a2836e92: Download complete
Digest: sha256:a8531b2e5fc6fea3a9bb88c598cde60b3b1a3ce50589fd3e7fb6c282735c31bc
Status: Downloaded newer image for docker/sandbox-templates:claude-code-docker

INFO: Started Docker daemon in 0.5s
Starting claude agent in sandbox 'claude-myProject'...
Workspace: C:\Users\████████\myProject
╭─── Claude Code v2.1.162 ─────────────────────────────────────────────────────────────────────────────╮
│                                               │ Tips for getting started                             │
│                 Welcome back!                 │ Ask Claude to create a new app or clone a repository │
│                                               │ ──────────────────────────────────────────────────── │
│                    ▐▛███▜▌                    │ What's new                                           │
│                   ▝▜█████▛▘                   │ Check the Claude Code changelog for updates          │
│                     ▘▘ ▝▝                     │                                                      │
│                                               │                                                      │
│   Opus 4.8 (1M context) · API Usage Billing   │                                                      │
│         /c/Users/████████/myProject         │                                                      │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────╯

 ▎ Opus 4.8 is here! Now defaults to high effort · /effort xhigh for your hardest tasks

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
❯ 
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
  ⏵⏵ bypass permissions on (shift+tab to cycle) · ← for agents                                                                                                              Not logged in · Run /login
Интерфейс Claude Code сразу после запуска sbx run claude. Видно скриншот терминала с pull-выводом Docker образа и запущенным Claude code

Интерфейс Claude Code сразу после запуска sbx run claude. Видно скриншот терминала с pull-выводом Docker образа и запущенным Claude code

Образ агента подтягивается на первом запуске и дальше идет из кэша. Следующий старт укладывается в секунды две-три. sbx run работает и без аргументов: открывается интерактивный TUI picker для выбора агента и рабочей директории, удобно для первой пробы.

TUI-dashboard sbx (открывается командой sbx без аргументов). Показывает карточки всех запущенных и остановленных sandbox с CPU, memory, портами плюс панель network governance с allowlist и логом обращений. Визуально демонстрирует, что sbx не голый CLI

TUI-dashboard sbx (открывается командой sbx без аргументов). Показывает карточки всех запущенных и остановленных sandbox с CPU, memory, портами плюс панель network governance с allowlist и логом обращений. Визуально демонстрирует, что sbx не голый CLI

В соседнем терминале можно открыть параллельную сессию:

$ sbx ls
NAME            AGENTSTATUS    WORKSPACE
claude-my-project   claude   running   /Users/andrew/my-project
$ sbx exec -ti claude-my-project bash
agent@claude-my-project:~$ whoami
agent
agent@claude-my-project:~$ cat /etc/os-release | head -1
PRETTY_NAME="Ubuntu 25.10"
agent@claude-my-project:~$ exit

Флаг -ti для sbx exec обязателен, если нужна интерактивная сессия. Без него shell стартует в неинтерактивном режиме.

Деталь для более полного понимания: sbx stop сохраняет состояние VM и можно выполнить команду sbx run claude-my-project и поднять с того же места, sbx rm удаляет microVM совсем. Рабочая директория на хосте не удаляется ни в одном из случаев. Где лежала, там и осталась. Sandbox живет именно между запусками, а не представляет собой контейнер на одну сессию.

Несколько вариантов запуска, которые я использую чаще всего:

sbx run claude ~/my-project                # Явное указание рабочей директории

sbx run claude . /path/to/docs:ro          # Дополнительные read-only-директории

sbx run claude -- --continue               # Передача флагов агенту через --

sbx run claude --branch feature/x ~/my-project # Изолированный git-worktree под ветку [https://docs.docker.com/ai/sandboxes/usage/#branch-mode]

sbx create claude ~/project                # Создать sandbox без старта агента

sbx run claude-my-project                  # Подключиться к существующему Sandbox

sbx ports claude-my-project --publish 8080:3000 # Пробросить порт sandbox на хост

Пояснения по каждой неочевидной команде:

🔻 -- --continue — всё после -- уходит агенту как есть. Без оберток и хитрых скриптов можно передавать любые CLI-флаги конкретного агента.

🔻 --branch feature/x — создает git-worktree в .sbx/<sandbox>-worktrees/<branch> и изолирует работу агента от main [4]. Полезный прием, если не хочется давать ИИ-агенту трогать основную ветку.

🔻 sbx ports — пробрасывает порт из sandbox на хост, когда агент собрал dev server или API. В этом случае сервис внутри sandbox должен слушать на 0.0.0.0, не на 127.0.0.1, иначе проброс не сработает.

За несколько месяцев работы накопилось несколько практических наблюдений, описания которых в документации нет.

Два агента в одном shell sandbox. Если переключаюсь между Claude и Codex в одном проекте, держу один shell sandbox (sbx run shell ~/my-project) и из него поочередно запускаю агентов локально внутри VM. Окружение не дублируется: npm-пакеты, Python venv, конфиги делятся на оба агента. В этом сценарии на хосте только одна microVM вместо двух — ресурсы экономятся, и проще синхронизировать скилы и инструкции между агентами. Подходит, когда хочется запустить разные агенты в одном проекте.

Git: read внутри sandbox, write с хоста. Принцип наименьших привилегий в чистом виде: агент внутри sandbox читает репозиторий, может смотреть разницу между коммитами и ветками, формулирует сообщение к коммиту, ставит изменения в индекс. Финальные git commit и git push я делаю с хоста, где лежат SSH- и GPG-ключи. Ключи внутри sandbox не нужны. Если агент случайно подменит коммит-хук или попытается переписать историю, инцидент останется внутри VM, репозиторий на удаленном сервере не пострадает. Один и тот же каталог .git/ в рабочей директории работает в двух разных контурах операций.

СРОЧНО В НОМЕР! Пока готовилась статья, Docker Sandbox научился подписывать коммиты ключами с хоста. Но в моем случае агент не делает коммит и пуш, поэтому для меня все остается по-старому.

«Залипший» sandbox. Один раз Claude Code отказался подхватывать новую модель, когда вышла версия Opus 4.7. Разбираться с состоянием VM было нерационально долго. Я попросил агент сложить плагины, скилы и важные конфиги в .backup/ в директории проекта. Это папка внутри рабочей директории, она доступна и на хосте, и в sandbox одновременно — изменения с одной стороны видны сразу с другой. Потом я сделал sbx rm claude-my-project, запустил sbx run claude заново, и агент сам, под моим чутким руководством, подтянул файлы из .backup/ обратно. Заняло несколько минут. Рабочая директория тут работает как мост между поколениями sandbox: никаких специальных команд для миграции данных не нужно, потому что директория доступна с обеих сторон.

Контейнеры живут между запусками, но хранить конфиги внутри sandbox (в ~/.claude/ внутри VM) все равно рискованно: такие файлы переживут sbx stop, но не переживут sbx rm. То, что должно сохраниться, кладется в репозиторий. Он остается доступен и на хосте.

Привычка, которая иногда встречается у пользователей и которую полезно отбросить, — класть все в один большой sandbox на все случаи жизни. Лучше держать гранулярность: отдельный sandbox под отдельный проект. Расход ресурсов на microVM не такой большой, чтобы экономить на изоляции, а импакт при инциденте сужается до пределов одного проекта.

Маленькая деталь в конце раздела: агент внутри sandbox может узнать, что он именно в sandbox. Спрашиваешь Claude Code, и агент честно отвечает, в каком окружении он сейчас живет, и это помогает. Например, агент может напрямую запросить у пользователя выдать разрешение на доступ к определенному домену, понимая, что он в sandbox с сетевыми политиками, вместо того чтобы часами долбиться в стену и искать причину отсутствия доступа по сети.

Запуск агента уложился в одну команду. Какие обращения он отправит во внешнюю сеть?

Сетевые политики

В sbx есть три пресета сетевой политики, и при первом sbx login CLI заставляет выбрать один пресет: по умолчанию опции «из коробки» нет [4].

Open. Весь исходящий трафик HTTP/HTTPS разрешен. Подходит для прототипа или быстрой разработки, когда стоимость ошибки маленькая.

Balanced. Deny by default плюс allowlist популярных ресурсов: пакетные реестры (npm, PyPI), GitHub, основные CDN, API крупных провайдеров моделей. Точный список не привожу: он эволюционирует. За актуальной выкладкой следите в документации Docker [6]. Это стартовая точка для повседневной деятельности, и документация Docker рекомендует начать с режима Balanced.

Locked Down. Заблокировано все, кроме явно разрешенного. Применимо в подозрительных сценариях, например при анализе малвари, или в случаях, когда есть явно недоверенный код: там лишний исходящий трафик нежелателен сам по себе.

Базовые команды управления политикой:

sbx policy set-default balanced                           # Пресет по умолчанию
sbx policy allow network -g api.anthropic.com             # Разрешить домен
sbx policy allow network -g "*.npmjs.org,*.pypi.org"      # Несколько доменов
sbx policy deny network -g ads.tracking.com               # Запретить домен
sbx policy ls                                             # Активные правила
sbx policy rm network -g --resource ads.tracking.com      # Снять правило
sbx policy reset                                          # Сбросить и переспросить
sbx policy log                                            # Лог запросов прокси (все sandbox)
sbx policy log my-sandbox                                 # Лог одного конкретного
sbx policy log --json                                     # Машиночитаемый вывод
sbx policy log --limit 50                                 # Последние 50 записей

Флаг -g делает правило глобальным для всех ваших sandbox. Если его не указать, политика привязывается к конкретному sandbox по имени. Например, sbx policy allow network my-sandbox api.example.com разрешит доступ только из my-sandbox. В примерах ниже я везде использую -g, потому что собираю общий профиль доступа на машину, но можно и точечный.

Несколько свойств, на которых я успел споткнуться или которые мне пригодились [6]:

  • Wildcard поддерживается. *.npmjs.org покрывает все поддомены, включая registry.npmjs.org, cdn.npmjs.org.

  • Deny beats allow. Если домен подпадает под оба правила, побеждает запрет. Это удобно для точечного отключения: добавляешь общий wildcard-allow на корпоративный домен и точечный deny на ad-домен поверх.

  • HTTP/HTTPS only. sbx policy allow влияет только на HTTP/HTTPS-домены. Другой TCP-трафик можно разрешить, прямо указав адрес и порт [5][6]. UDP- и ICMP-трафик заблокирован на уровне сети и не может быть разблокирован сетевыми политиками. Это намеренное архитектурное свойство, и именно оно закрывает DNS-туннелирование, описанное в предыдущей статье, — в случае если на вашем DNS-сервере в инфраструктуре настроена фильтрация по доменам… Ведь настроена? Да?

  • Трафик на локальные адреса и в частные сети блокируется и требует от пользователя целенаправленного разрешения в политиках. Зачем? Потому что бывает и такое.

За два месяца активного использования я сделал несколько практических наблюдений.

По умолчанию у меня установлен режим Balanced или Open. Пресет Locked Down включаю отдельно, под конкретную задачу, когда исходящий трафик нежелателен сам по себе и проще выставить «Все запрещено», а потом точечно разрешить только то, что понадобится для конкретных действий. Для рабочих проектов Balanced дает нужный список разрешенных доменов «из коробки» без раздельной настройки под каждый репозиторий.

Агенты конструктивно реагируют на блокировку. Claude, упершись в закрытый домен, не уходит в retry loop и не пытается обойти политику. Он возвращается к пользователю с сообщением вида: «Для этого шага нужен доступ к api.example.com, разрешишь?». Решение о расширении доверенного списка принимаю я, не агент. Это и есть human in the loop, ради которого выстраивается изоляция: контроль над тем, куда агент дотягивается, остается на пользователе, а не растекается по спискам доступа и базовых политик.

Логи прокси информативные. В них видно, что запрошено, что пропущено по доверенному списку, что заблокировано: домен, время и sandbox, из которого пришел запрос. Это бесплатный аудит сетевой активности агента: не нужно отдельно настраивать tcpdump или подключать SIEM-систему, чтобы увидеть, что Claude хотел сходить в api.openai.com, а вы его туда не пускали.

Вывод sbx policy log с двумя секциями (Blocked requests / Allowed requests), таблицей. Визуальный пример «бесплатного аудита».

Вывод sbx policy log с двумя секциями (Blocked requests / Allowed requests), таблицей. Визуальный пример «бесплатного аудита».

Попыток «выйти» из sandbox не было. За два месяца работы ни разу не видел в логах попытки агента дотянуться до запрещенного домена самостоятельно: все блокировки были по легитимным запросам, которым в моей политике не нашлось разрешения. Это слабая выборка для статистики, но как ориентир она успокаивает: базовые установки Balanced не создают постоянного фона ложноположительных алертов.

И еще один практический штрих про режим Locked Down. Когда я запускаю недоверенный код, то ставлю sandbox в Locked Down и явно разрешаю один-два домена для конкретной задачи (например, *.virustotal.com для проверки хешей). Любая попытка достучаться изнутри sandbox куда-то еще видна в логах и блокируется на уровне сети, а не на уровне правил детекта. Это не полное лабораторное окружение, и не рекомендуется так делать, хотя этот подход и лучше, чем просто открыть подозрительный архив на хосте без изоляции.

С исходящим трафиком разобрались. Но прежде чем разбирать ключи, которые агент будет подкладывать в такой трафик, остановлюсь на решении Docker для организации, а потом перейду к одной поведенческой детали, которая в sandbox работает иначе, чем на голом хосте.

Управление политиками безопасности песочниц на уровне организации

Это платный продукт. На момент написания у Docker есть Docker AI Governance — отдельная подписка, через которую администратор задает сетевые и файловые политики напрямую из консоли администратора. Эти правила имеют приоритет над локальными sbx policy на машине разработчика. Администратор получает централизованный допуск, возможность запретить определенные домены (для всех sandbox организации одновременно), возможность управлять тем, какие пути на хосте разработчикам разрешено монтировать как рабочие директории (нельзя смонтировать /etc или ~/.ssh в sandbox, если админ так настроил), и опциональную делегацию: админ может позволить разработчикам добавлять дополнительные allow-правила локально, но не снимать его запрет.

Это решает классическую корпоративную задачу: «У меня в инфраструктуре сто разработчиков, и я хочу, чтобы никто из них не мог сам разрешить sandbox ходить в любой произвольный домен или смонтировать чувствительный путь к рабочей директории».

Соседние enterprise-инструменты Docker, которые работают в том же сегменте Docker Business, но решают другие задачи:

  • Hardened Docker Desktop с Enhanced Container Isolation — ECI запускает контейнеры в Linux user namespaces, это защита самого Docker Desktop от эскалации привилегий (неспецифично для sbx);

  • Settings Management — с помощью него админ навязывает конфигурацию Docker Desktop всем разработчикам (через JSON-файл или Admin Console);

  • Registry Access Management — для централизованного контроля доступа к реестрам образов;

  • Image Access Management — для контроля того, какие образы из Docker Hub можно скачивать.

Docker AI Governance — AI/sbx-специфичная часть стека, не интегрированная с остальными в единый продукт и живущая в отдельной подписке, но адресующая ту же enterprise-картину: безопасное использование Docker и его агентов в организации [10]. На обычной подписке Personal, Pro, Team или Business этой возможности нет: политика sbx остается локальной для каждой машины, и для enterprise-кейса есть только внешние механизмы: governance-процессы и MDM, policy push на установку. Ниша локального аудита и контроля действий ИИ-агента — отдельный разговор, к которому мы еще вернемся за рамками этой статьи.

--dangerously-skip-permissions

У многих агентов есть флаг вида --dangerously-skip-permissions (или --yolo, в зависимости от агента), который отключает необходимость подтверждения каждого действия у пользователя. На голом хосте такая опция выглядит как минимум подозрительно. Имя флага не зря содержит слово dangerously: за ним стоит реальный риск — агент запускает все что угодно, не спрашивая. При негативном сценарии вы сможете только наблюдать, как агент быстро и по кусочкам аннигилирует вашу систему.

Внутри sandbox этот флаг включен по умолчанию у большинства поддерживаемых агентов, и Docker в FAQ обосновывает это прямо: радиус поражения уже определен архитектурой. Сам sandbox — это и есть граница безопасности. Поскольку агенты крутятся в изолированной microVM с сетевыми политиками, с изоляцией секретов и без доступа к хосту за пределами рабочей директории, обычные причины запрашивать подтверждение каждой команды (защита от деструктивных действий, контроль сетевых обращений, ограничение модификации файлов) уже закрыты слоями изоляции [9].

На практике это снимает с меня целый пласт задач, связанных с микроконтролем, которые раньше съедали ощутимое время. Без sandbox каждое npm install, cargo build, перемещение файла или sed-замена в большом проекте либо подтверждается вручную, либо вызывает тревогу: «А вдруг агент сейчас сделает что-нибудь не то?». Внутри sandbox этой тревоги нет: если ошибется, ошибка ограничена пределами VM, рабочая директория восстанавливается из Git, sandbox пересоздается командой sbx rm + sbx run. Я могу держать несколько агентов параллельно на разных проектах и не отвлекаться на согласование каждого действия.

Одно исключение, о котором стоит помнить. Если вы запускаете агент через shell sandbox (то есть выполняя команду sbx run shell ~/my-project), а потом внутри руками поднимаете, например, claude, то в таком случае флаг --dangerously-skip-permissions нужно указать явно: shell sandbox не знает, какой агент в нем живет, и мод YOLO по умолчанию не включается.

Теперь — к ключам, которые агент будет подкладывать в исходящие запросы.

Секреты

Чаще всего API-ключ передается напрямую в API-запросе через ANTHROPIC_API_KEY=... в окружении агента, однако этот способ устарел. Проблема в том, что переменная окружения внутри VM доступна любому процессу, в том числе запущенному вредоносным пакетом, который агент только что подтянул. sbx решает эту задачу через прокси на стороне хоста [7][8]:

  1. Хост хранит учетные данные через sbx secret set.

  2. При запросе, например, к api.anthropic.com прокси перехватывает HTTP-вызов.

  3. Прокси добавляет Authorization: Bearer sk-ant-... в заголовки.

  4. Агент внутри VM получает только ответ API. Реальное значение ключа в VM не попадает.

sbx secret set anthropic       # CLI запросит значение ключа с маской ввода

sbx secret set github          # GitHub PAT, npm token и т. п.

sbx secret ls                  # Список без значений

sbx secret rm anthropic        # Удалить

Секреты можно ставить глобально или для конкретного sandbox.

Важно учитывать ограничение sbx secret: команда работает с фиксированным набором провайдеров (Anthropic, OpenAI, GitHub и другими). Для кастомных переменных окружения вроде BRAVE_API_KEY или внутреннего корпоративного токена путь идет через /etc/sandbox-persistent.sh внутри sandbox: это shell script, который sbx подгружает при каждом входе в Bash внутри sandbox. Переменные оттуда становятся доступны интерактивным сессиям и агентам, запущенным через sbx run [9]. Один нюанс: если вы вызываете команду напрямую через sbx exec <name> <command>, sbx запускает ее без shell — и файл /etc/sandbox-persistent.sh не подхватывается. В этих случаях оборачивайте команду в bash -c "...", чтобы окружение подгрузилось [9].

Лично я sbx secret не использовал: с Claude Code авторизация идет через webflow, сессия обновляется в необходимых интервалах, и отдельный токен в локальном хранилище мне не нужен. Когда я буду работать с провайдерами, требующими открытого API-ключа внутри запроса, сценарий поменяется, но пока такого не было.

Сокрытие секретов — лишь частный случай. Возвращаюсь к шести классам угроз из первой статьи цикла: что из них изоляция реально закрывает?

Что закрывает изоляция

Привязываю каждый класс к sbx. Это оценка из опыта — лабораторной точности здесь ждать не стоит. В следующей части серии сделаю полный разбор, сравню следующие сценариев: агент на хосте, агент в контейнере, агент в Docker Sandbox, и расскажу про воспроизводимые эксперименты, которые можно будет повторить у себя.

Класс угрозы из первой части статьи

Закрывает ли ее sbx

Почему

Случайный rm -rf

✅ Полностью

Файловая система вне рабочей директории недоступна

Промпт-инъекция

❌ Нет

Модель получит ту же инструкцию, sbx ограничивает только blast radius

Малварь, использующая агент

⚠️ Частично

Вредонос крутится в microVM, до хост-секретов не дотянется

Атака на цепочку поставок через агент

⚠️ Частично

Зависимость отравлена, но не выходит за периметр sandbox

Кража токенов

⚠️ Частично

Хост-секреты закрыты, секреты в рабочей директории — нет

Компрометация CI/CD

⚠️ Частично

Если CI-токен попал в sandbox, то он доступен изнутри. Sandbox — не магия

Один ✅, один ❌, и четыре ⚠️. Это и есть центральный тезис статьи: sbx помогает снизить радиус потенциального поражения, а не предлагает универсальное решение. Он действительно делает невозможным случайный rm. Ту часть промпт-инъекции, которую обрабатывает LLM, он принципиально не закрывает: это происходит на уровне модели и приема данных. Все остальное нужно для ограничения последствий, а не для предотвращения события.

«Частично» дает драматическую разницу между сценарием без изоляции и с sbx. Для большинства угроз, описанных в первой статье цикла, разница между «Без изоляции» и «Использование через sbx» сводится к разнице между «Хост скомпрометирован» и «Sandbox скомпрометирован, хост целый». В первом случае атакующий получает рабочую станцию разработчика с SSH-ключами, токенами и доступом к корпоративной VPN; во втором — изолированный sandbox размером в один проект, без хост-секретов, с мониторингом исходящего канала и без Docker-демона хоста. Для большинства моделей угроз этого хватает, чтобы переместить инцидент на уровень ниже.

В следующей статье цикла я планирую поставить вопрос иначе: не «закрывает или нет», а «насколько именно сужается радиус поражения относительно запуска на хосте без песочницы и обычного контейнера и какие сценарии все равно проходят насквозь». Для этого нужны эксперименты: DNS-туннелирование при разных пресетах, тестирование поведения под Locked Down, попытки доступа к сетевым ресурсам разной степени подозрительности и т. п. Всему этому место в отдельном материале.

Куда дальше

На этом я закончил с базовыми настройками и основными рычагами управления защитой. За несколько месяцев использования sbx заменил мне отдельные виртуальные машины, которые я раньше держал под ИИ-агенты: он стартует быстрее, ставится проще и при этом дает аналогичную изоляцию.

Если резюмировать, базовый путь выглядит так: вы ставите sbx из своего пакетного менеджера (команды для macOS, Windows и Linux я приводил выше, в разделе «Установка»), делаете sbx login, на начальном этапе выбираете пресет Balanced, дальше в проектной директории запускаете sbx run claude или <Имя вашего агента>. Агент работает в изолированной microVM с сетью в режиме доступа только к разрешенным ресурсам и MITM-прокси на стороне хоста для секретов. Хост при этом остается в большей безопасности, чем при запуске агента на нем. Сам переход занимает несколько минут. После него для пяти из шести классов угроз из моей предыдущей статьи потенциальный импакт сужается до периметра sandbox VM. Реализацию шестой угрозы, промпт-инъекции, изоляция не предотвращает. Инъекция приходит в модель, как и раньше, однако то, что скомпрометированный агент способен сделать далее, ограничено.

Одна честная оговорка: sbx — продукт в фазе активной эволюции. Пока я писал эту статью, каталог поддерживаемых агентов sbx вырос с восьми до десяти. Добавились:

  • Cursor — CLI-режим Сursor называется agent (не IDE Cursor с GUI), запускающийся в моде YOLO по умолчанию;

  • Droid — AI-агент Factory (требуется Factory-аккаунт), которого в изначальной версии не было.

За те месяцы, которые прошли между моими первыми проверками (Docker Sandbox в феврале, sbx — в апреле) и моментом, когда вы это читаете, у Docker неоднократно менялись набор поддерживаемых агентов, синтаксис отдельных команд и статус параллельной имплементации в Docker Desktop. Архитектура и принципы, о которых я пишу (microVM, прокси на стороне хоста, deny by default), стабильны и переживут текущий цикл переименований. Меняется набор CLI-флагов и эргономика команд — это вопрос пользовательского опыта, а не модели изоляции. Конкретные имена команд, флагов и подкоманд сверяйте с актуальной docs.docker.com перед запуском.

Заметка про устаревшую имплементацию: у docker sandbox в Docker Desktop был флаг

--bypass-host, который выводил конкретные домены из MITM-инспекции прокси. В начале 2026 года этим флагом я чинил странное поведение Codex в связке с docker sandbox: Codex обнаруживал атаку и отказывался отправлять запросы через MITM-прокси, пока docker sandbox не был запущен с командой --bypass-host *.openai.com. Поведение касалось конкретной устаревшей имплементации, к sbx как продукту оно отношения не имеет. В актуальном sbx эквивалентного флага я не нашел. Воспроизвести ситуацию в рамках статьи не успел. Если столкнетесь с похожим — пишите в комментариях, разберемся вместе.

Статья посвящена рабочему сценарию — применению агента в sandbox для проекта. Но sbx можно использовать и для персонального ассистента с доступом к личным данным (к документам, заметкам, почте) через локальную интеграцию. Например, OpenClaw (в первой статье, в разделе «Кража данных и токенов», я разбирал инцидент, в котором конфиги OpenClaw стали целью инфостилер-кампании). Сценарий с персональным ассистентом требует иной конфигурации образа: другого набора инструментов, политик сети, другой модели доверия к рабочей директории.

Docker Sandbox позволяет собирать кастомные образы. Желающих поупражняться приглашаю в комментарии и предлагаю составить конфиг для личного ассистента (желательно с аргументацией, почему так, а не иначе).

За кадром остались три вопроса:

  1. Как именно работает гипервизор-изоляция изнутри?

  2. В ходе каких экспериментов можно определить реальные границы защиты?

  3. Как собрать кастомный образ под конкретный сценарий?

Это материал для следующей части серии. Если тема зайдет и в комментариях будет интерес, соберу третью часть.

Источники

На этом пока всё!

Если хотите больше такого, заходите в мой Telegram-канал, который я веду совместно с замечательными людьми. Там авторское мнение по теме ИИ и кибербеза, мемы из частной коллекции и многое другое. Буду рад!