AI-агенты в песочнице: как я перестал бояться давать Claude доступ к системе
Долго сопротивлялся тому факту, что Claude Code имеет полный доступ к моему терминалу (не открытие, но я всегда на эту часть знаний закрывал глаза). Может запускать любые bash-команды. Читать ~/.ssh, переменные окружения с токенами. Всё.
Галлюки тоже с ростом проекта и его сложностью – возрастают. Например, он пытался запустить несуществующую команду. Безобидно, конечно. Но мысль осталась: а что если следующая галлюцинация будет с rm -rf или curl с моими секретами куда-нибудь не туда? Тем более что обнаруженные промпт-инъекции всё чаще находят уже те, кто пострадал.
Проблема: AI-агенты – это не просто чатботы
Есть принципиальная разница между ChatGPT в браузере и Claude Code / Cursor Agent. Первый может только текст генерировать. Вторые – выполняют команды. Реальные команды на твоей машине.
Что видит AI-агент в типичном сетапе:
- Полный доступ к файловой системе (включая ~/.ssh, ~/.config)
- Все переменные окружения (SERVER_1_API_KEY, BLA_BLA_ACCESS_KEY, всё что ты там экспортируешь)
- Возможность запускать любые shell-команды
- Историю bash с твоими прошлыми командами
- Git-коммиты, хронологию и тд
Галлюцинации + shell = потенциальный риск. Как ранее говорил, AI иногда выдумывает команды, путает синтаксис, или пытается сделать «лучше» без спроса. Особенно когда контекст уже перевалил за 90% в допустимом буфере.
Пара реальных сценариев, которые могут случиться:
- AI решает «почистить» временные файлы и промахивается с путём
- Отправляет диагностику куда-то через curl (видел такое в логах у другого блогера)
- Добавляет вредоносный MCP в конфигуратор (а supply chain атаки – уже не теория)
- Читает .env файл и включает его содержимое в ответ, который уходит в API
Не то чтобы это происходит каждый день. Но когда работаешь с чем-то важным – хочется подстраховаться. Да и параноик я по жизни.
А ещё с ростом проекта ты начинаешь обзаводиться тех. долгом и сессия работы агента начинает растягиваться (у меня стабильно 10+ минут на каждую таску) + уже работаю в двух терминалах, знаю людей, у которых их уже 6+. Хочется в момент ожидания не тиктоки листать и в телеге залипать, а следующие таски запускать. Это та самая дофаминовая петля – мозг требует ещё и ещё результатов. Но такой подход ломается, если ты не запускаешь Claude в режиме без ограничений (чтобы каждый чих не апрувить и согласовывать).
Решение: Dev Containers как песочница
Использую: Dev Container. Это способ запускать окружение разработки внутри Docker-контейнера. VS Code (или Cursor) подключается к нему, и ты работаешь как обычно. Только изолированно от хост-системы.
Почему именно devcontainer, а не просто Docker:
- Интеграция с IDE из коробки – расширения, терминал, отладка работают прозрачно
- Стандартизированный формат – devcontainer.json понимают VS Code, Cursor, Antigravity
- Удобное управление секретами через remoteEnv
- Можно настроить один раз и забыть
Философия простая: AI в контейнере. Сломает что-то – пересоздашь за минуту. Хост-система в безопасности.
Чем не угодили автору изолированные git-ветки и просто deny в настройках агентов?
- Я и так пользуюсь изолированными ветками для всех задач (и сессий, в которых понимаю, что будут изменения в нескольких файлах). Вернуться на пару коммитов раньше и начать заново намного быстрее, чем заново контейнер поднимать.
- Deny можно замутить, но я за месяцы работы так и не смог толком сформировать глобальный файл конфигурации, чтобы его можно было ctrl+c / ctrl+v из одного проекта в другой. А ещё, поверьте, если он захочет получить доступ к файлу – он этот deny найдёт как обойти. У меня до абсурда кейс был: когда он не смог получить доступ, пошёл написал shell-скрипт, не смог его запустить, пошёл в python, сделал py-скрипт и там всё-таки добрался до нужного.
Что из себя представляет devcontainer
Дисклеймер: я очень, подчеркну, очень мало работал с контейнерами, но мне эта тема интересна. И если я где-то в чём-то перемудрил или наоборот сделал хуже – можете кинуть какашку в комментарии, но я буду безмерно благодарен, если дадите конструктивный совет 🔥
Вот примитивная конфигурация, которую использую (это проект по выгрузке постов из телеги в md-формате).
devcontainer.json:
{"name":"my-project","build":{"dockerfile":"Dockerfile"},"features":{"ghcr.io/devcontainers/features/node:1":{"version":"20"}},"remoteEnv":{"TELEGRAM_API_ID":"${localEnv:TELEGRAM_API_ID}","TELEGRAM_API_HASH":"${localEnv:TELEGRAM_API_HASH}","ANTHROPIC_API_KEY":"${localEnv:ANTHROPIC_API_KEY}"},"mounts":["source=project-data,target=/workspaces/project/data,type=volume"],"runArgs":["--cap-drop=ALL","--security-opt=no-new-privileges"],"postCreateCommand":"bash .devcontainer/post-create.sh","remoteUser":"vscode"}
Чуть-чуть пояснения:
--cap-drop=ALL – сбрасываем все Linux capabilities. Контейнер не может менять сетевые настройки, монтировать файловые системы, работать с устройствами. Только базовые операции.
--security-opt=no-new-privileges – процессы внутри контейнера не могут повышать привилегии. Даже если AI найдёт какой-то эксплойт – не сможет им воспользоваться.
remoteEnv – секреты передаются из хост-системы в контейнер, но не записываются в образ. Если кто-то получит доступ к образу – секретов там не будет.
Named volume для данных – персистентные данные (например, сессии) хранятся в Docker volume, а не в bind mount. Изоляция от хост-файловой системы.
remoteUser: vscode – работаем от непривилегированного пользователя, не от root.
Dockerfile – минимальный:
FROM mcr.microsoft.com/devcontainers/python:3.12RUN apt-get update && apt-get install -y --no-install-recommends \ libffi-dev \ libssl-dev \ && rm -rf /var/lib/apt/lists/*WORKDIR /workspaces/projectUSER vscode
post-create.sh – инициализация после создания контейнера:
#!/bin/bashset -e # Node.js доступен здесь (установлен через features) sudo npm install -g @anthropic-ai/claude-code # Python окружение python -m venv .venv source .venv/bin/activate pip install -r requirements.txt
Всё это дело можно упростить следующим образом:
- Открываете любого AI-агента и проект, который раньше у вас запускался не в контейнере.
- Создаёте ему задачу следующего типа:
Данный проект должен иметь возможность запускаться в devcontainer. Создай необходимые файлы конфигурации. Конфигурацию создай на основе описания проекта, зависимостей. По необходимости создай скрипты по установке дополнительных инструментов после сборки образа.
Во что я вляпался, пока всё это отлаживал
Показать только результат – скучно же.
npm недоступен при сборке образа. Пу-пу-пу. Хотел установить Claude Code CLI прямо в Dockerfile через npm install -g. Получил ошибку: npm not found.
Причина: Features (включая Node.js) применяются ПОСЛЕ сборки Dockerfile. Это, видимо, особенность архитектуры devcontainers. Dockerfile собирается первым, потом накатываются features, потом запускается postCreateCommand. Ну либо я рукожоп.
Решение: перенёс установку CLI в post-create.sh. Там Node.js уже доступен.
Кэширование PATH в bash. После установки Claude Code и других CLI-полезностей через npm новый путь добавляется в PATH. Но если терминал уже открыт (а я делаю это всё внутри Cursor) – bash помнит старый PATH. Получаешь «claude: command not found», хотя всё установлено.
Решение: перезапустить терминал или выполнить hash -r для сброса кэша команд.
Секреты не пробрасываются. Настроил remoteEnv, но переменные пустые внутри контейнера.
Причина: переменные должны быть экспортированы на хосте ДО запуска контейнера. Если добавил export TELEGRAM_BLA_BLA_KEY=... после – нужно пересоздать контейнер.
Чего этот подход НЕ решает
Важно понимать ограничения.
AI всё ещё видит код проекта. Сам ору с этого тезиса, но следующая мысль важна. Если в коде есть захардкоженные секреты (не делайте так) – AI их увидит. Вычищайте всё заранее.
Сетевой доступ есть. Контейнер может делать запросы в интернет. Можно ограничить через --network none, но тогда сломается npm install, pip install, git clone и вообще всё полезное. Возиться с white-списком мне лень.
Секреты в remoteEnv доступны AI внутри контейнера. Внутри контейнера AI может прочитать эти переменные (если захочет). Разница в том, что он не видит ВСЕ секреты хост-системы – только те, что явно пробросили.
Первый запуск = сборка образа. Готовьтесь ждать несколько минут. У меня две минуты на чистую сборку. Потом кэш спасает.
Не защищает от логических ошибок. Если AI сгенерирует код с SQL-инъекцией – devcontainer никак не поможет. Это про изоляцию окружения, не про code review.
Когда это нужно, а когда overkill
Используй devcontainer, если:
- У тебя на устройстве корпоративные проекты
- Работаешь с реальными API-ключами и секретами
- Проект связан с продакшн-инфраструктурой
- Есть доступ к чувствительным данным (клиентские данные, финансы)
- Хочешь воспроизводимое окружение для команды
- Паранойя – твоё второе имя
Не заморачивайся, если:
- Pet-проект без секретов
- Личный комп, на котором ничего важного нет
- Учебный код
- Публичный open-source без credentials
- Доверяешь AI больше, чем я
Как сделать такое же у себя?
Если решил попробовать, вот что нужно:
- Установи Docker Desktop и Dev Containers (расширение для Cursor).
- Создай папку .devcontainer в проекте
- Добавь devcontainer.json с базовой конфигурацией
- Добавь runArgs с --cap-drop=ALL и --security-opt=no-new-privileges
- Пробрось только нужные секреты через remoteEnv
- Установи AI-инструменты в postCreateCommand, не в Dockerfile
- Проверь что всё работает: Cmd+Shift+P → «Reopen in Container» в IDE
Занимает 15-20 минут на первую настройку.
AI-агенты – новая категория инструментов, и практики безопасности для них ещё формируются. Dev Containers – один из возможных подходов, который лично мне даёт спокойствие при работе с Claude Code на проектах с секретами.
А вы как защищаете систему от AI-агентов? Или просто доверяете и не паритесь? Делитесь опытом.