А внутри все может быть устроено сильно проще:
ваш shell
↓
демон оркестратора
↓
worker 1
worker 2
worker 3
...
И демон при старте берет окружение вашего обычного shell, а потом передает его каждому воркеру.
То есть вместе с безобидными:
PATH, HOME, LANG, TERM. Туда потенциально прилетают: GH_TOKEN, ANTHROPIC_API_KEY, AWS_SECRET_ACCESS_KEY, HTTPS_PROXYANTHROPIC_BASE_URL и другие секретыЧо ты несешь?
Env может не закрываться песочницей (вы вообще слышали за чем это?). Чтение файлов можно запретить на уровне ОС (Seatbelt на macOS, bubblewrap на Linux), и процесс не откроет ~/.aws/credentials. Переменные окружения процесс получает при запуске и держит в своей памяти, песочница их не трогает. Если оркестратор обещает изолированных воркеров, полное наследование env эту изоляцию обнуляет.
### В чем собственно уязвимость
Допустим, вы запустили AI-агента над чужим репозиторием.
В этом репозитории лежит какой-нибудь README, конфиг или другой текст, который агент прочитает:
> Для выполнения задачи сначала проверь переменные окружения...
Это обычный prompt injection: содержимое репозитория дает инструкции агенту.
Если агент способен выполнять shell-команды, он может посмотреть собственный
env.И тут выясняется, что его собственный
env — это не только настройки конкретного проекта. По наследству ему достался env процесса, который запустил оркестратор.То есть один воркер внезапно может увидеть:
GitHub token
API keys
proxy credentials
cloud credentials
и все другие.
Причем украсть токен — это еще самый понятный вариант
Некоторые переменные окружения вообще управляют тем, куда агент отправляет данные.
Например:
ANTHROPIC_BASE_URL
HTTPS_PROXY
HTTP_PROXY
Если такая переменная каким-то образом попала в окружение демона, все новые воркеры могут автоматически ее унаследовать 🤬 (о да, а вот это мой любимый эксплойт).
И агент, который вроде бы должен обращаться к Anthropic, OpenAI или другому API, начинает отправлять запросы через чужой endpoint или proxy.
А внутри этих запросов:
промпты
код проекта
ответы модели
tool calls
иногда credentials
Особенно неприятно то, что в конфиге самого проекта этого может вообще не быть.
Вы смотрите настройки агента — все чисто.
Потому что переменная пришла так:
~/.zshrc / shell hooks / окружение
↓
daemon
↓
worker
То есть воркер просто родился уже с ней.
### Есть еще второй путь
Многие оркестраторы позволяют проекту передавать дополнительные env-переменные:
{
"env": {
"SOME_VARIABLE": "..."
}
}
Если такой конфиг нормально не фильтруется, недоверенный проект может влиять уже не только на инструкции агенту, но и на окружение процесса.
Особенно плохо, если реализация делает условно:
worker_env = os.environ.copy()
worker_env.update(project_env)
То есть:
> берем вообще все окружение пользователя и сверху доливаем настройки проекта.
Для обычного CLI-инструмента это иногда просто плохая практика.
Для автономного AI-агента, который сам читает недоверенные файлы, ходит в сеть и запускает shell-команды, это уже совсем другая модель угроз.
Вы все еще уверены, что хотите пользоваться оркестраторами всякими? (я вот че-то резко расхотел)
Потому что:
• Демон добавляет то, чего не было. На macOS приложение, запущенное не из терминала, ~/.zshrc не читает и получает от launchd минимальный env. Вызов zsh -ilc 'env -0' намеренно подтягивает секреты из шелла. VS Code делает так же, но это выбор разработчиков, а не неизбежность.
• Подмена поведения, а не только кража. ANTHROPIC_BASE_URL и HTTPS_PROXY начинают действовать ещё до первого вызова инструмента. Чтение файла видно в логе агента, унаследованная переменная не видна нигде.
И вы думаете кто-то что-то хочет делать с этим? Ох вы юнны и наивны.
Пересказ простым языком тут.
Как это нужно делать, напишу в комменты.