Это четвертая часть нашей серии «Истории ужасов об ИИ-агентах для написания кода», в которой мы рассматриваем реальные инциденты безопасности, связанные с ИИ-агентами, и то, как Docker Sandboxes предотвращают доступ агентов к учетным данным на уровне выполнения.
В первой части мы разобрали шесть категорий сбоев ИИ-агентов и причины, по которым они продолжают происходить. Агент работает от вашего имени, с вашими правами доступа к файловой системе и вашими учетными данными, и ничто не стоит между решением модели и выполнением команды в оболочке. Во второй части мы подробно рассмотрели инцидент с rm -rf ~/. В третьей части мы перенесли ту же проблему в облачную производственную среду. Проблема сохраняет учетные данные в поле зрения, но меняет вопросы: вместо того чтобы спрашивать, что агент делает с хранящимися у него секретами, мы спрашиваем, что происходит с самими секретами.
Сегодняшняя история ужасов: агент, который прочитал ключи каждого
26 августа 2025 года в npm были опубликованы вредоносные версии пакета сборки Nx. Nx загружается около четырех миллионов раз в неделю, и скомпрометированные релизы содержали post-install хук, указывающий на файл telemetry.js:
Post-install хук срабатывает сразу после завершения установки, поэтому полезная нагрузка запускалась на каждой машине, скачавшей пакет, без открытия файлов или проверки различий (diff). CI-раннеры попались так же, как и все, у кого расширение Nx Console проверяло наличие обновления версии в этот период. Пакеты попали в npm напрямую, без подтверждения происхождения. Кампания получила название s1ngularity от публичных репозиториев, созданных для хранения украденных данных.
Затем telemetry.js сделал то, что делают похитители учетных данных: просканировал файлы .env, закрытые SSH-ключи, облачные конфигурации, токены npm и GitHub, а также хранилища кошельков. Эта часть является рутинной. Что сделало s1ngularity достойным упоминания, так это следующий шаг: вместо того чтобы использовать собственный сканер, скрипт проверял машину на наличие уже установленного ИИ-агента для написания кода и передавал эту задачу ему.
В этом выпуске вы узнаете:
- Как отравленный npm-пакет превратил установленные ИИ-интерфейсы командной строки (CLI) в сканеры учетных данных
- Почему --dangerously-skip-permissions и их аналоги являются сутью всей атаки
- Почему ИИ-ассистенты допускают утечку секретов примерно в два раза чаще, чем при обычном написании кода
- Как Docker Sandboxes полностью исключает доступ агента к учетным данным
Подпись: Комикс, иллюстрирующий, как вредоносный post-install скрипт обнаруживает установленного ИИ-агента, вызывает его с флагами обхода разрешений и использует для перечисления секретов, к которым у разработчика уже есть доступ.
Проблема
Большинству похитителей учетных данных приходится приносить свои инструменты. Они поставляют сканер, сами обходят файловую систему и работают по жестко заданному списку мест, где обычно хранятся секреты. telemetry.js нашел более дешевый путь. Он искал ИИ-агента, который уже был установлен, в который уже выполнен вход и которому уже разрешено читать все, что может прочитать разработчик, и вместо этого заставлял его работать.
Все три агента, которые он искал, имели способы запуска без остановки для подтверждения. Эти флаги существуют по уважительной причине, так как подтверждение чтения каждого файла становится утомительным, как только вы доверяете задаче, которую передали:
- --dangerously-skip-permissions в Claude Code
- --yolo в Gemini CLI
- --trust-all-tools в Amazon Q
Вредоносное ПО устанавливало их самостоятельно. Весь механизм выбора представляет собой таблицу поиска с тремя записями, по одной для каждого CLI, о котором ему известно:
Скрипт проверяет, какие из трех бинарных файлов присутствуют, запускает тот, который находит, и захватывает вывод. PROMPT — это место, где находятся инструкции, и они читаются как обычная рабочая задача. Он велит агенту искать из домашнего каталога на глубину до восьми уровней, сопоставлять имена файлов со списком, включающим .env, id_rsa, keystore и несколько форматов кошельков, и записывать каждый абсолютный путь, который он находит, в /tmp/inventory.txt. Он также велит агенту не использовать sudo, что является способом злоумышленника избежать запроса пароля, который выдал бы его.
Разделение труда — это часть, над которой стоит задуматься. Агент выполнял поиск, потому что он был хорош в этом и потому что ничто его не останавливало. Вредоносное ПО занималось кражей, что является легкой половиной дела, как только у вас есть список путей. Здесь не было эксплойта, повышения привилегий или песочницы, из которой нужно было бы сбежать. Агент уже был установлен, уже аутентифицирован и уже мог читать весь домашний каталог разработчика, и он был вызван с отключенным флагом запроса разрешений.
Масштаб проблемы
Согласно отчету GitGuardian «State of Secrets Sprawl 2026», в 2025 году в публичный GitHub было добавлено около 28,65 миллиона новых жестко закодированных секретов, что на 34% больше по сравнению с прошлым годом. В этой цифре скрыто число, которое важно для нас: тот же отчет показывает, что уровень утечки секретов в коде, написанном с помощью ИИ, примерно в два раза выше, чем в среднем по GitHub. Код, написанный с помощью агента, допускает утечку учетных данных примерно в два раза чаще, чем код, написанный без него.
Механизм прост. Агенту, которому поручено настроить интеграцию API, нужно прочитать .env проекта, чтобы определить, как называется ключ, и в этот момент «живая» учетная запись попадает в рабочий контекст модели. Оттуда он может добраться до сгенерированной конфигурации, тестового фикстуры или коммита, потому что ничто на этом этапе не отличает реальное значение от заполнителя, который должен был там находиться. У разработчика, проверяющего те же изменения, есть момент, чтобы заметить это. Агент, генерирующий и фиксирующий код со скоростью машины, этого не делает, и во многих случаях проверяющий тоже.
Обе истории основаны на одном и том же свойстве. Агент на вашей машине работает от вашего имени, с вашим доступом к файловой системе и вашими учетными данными, и нет более узкой идентичности, к которой он мог бы вернуться. Именно это позволяет «живому» ключу утечь из .env в коммит, и это же позволило отравленному пакету направить уже авторизованного агента в домашний каталог. Одно — это случайность, другое — атака, но для их работы требуются идентичные условия.
Технический разбор: как npm install превращается в утечку учетных данных
Подпись: Диаграмма, показывающая, как post-install скрипт заимствует уже авторизованный ИИ-CLI для чтения учетных данных, которые разработчик оставил в пределах досягаемости.
Вот как разворачивается инцидент, шаг за шагом.
1. Установка
Разработчик или CI-раннер скачивает отравленную версию Nx, обычно как транзитивную зависимость на несколько уровней ниже. В команде нет ничего необычного, а показанный ранее post-install хук делает все остальное. Полезная нагрузка проверяет платформу перед всем остальным и завершает работу на Windows, поэтому под угрозой оказались машины на macOS и Linux.
2. Инвентаризация
Скрипт обходит обычные места хранения учетных данных, которые на обычной рабочей станции являются именно теми местами, где живут рабочие учетные данные.
3. Заимствованный агент
Вместо того чтобы полагаться только на собственное сканирование, скрипт проверяет наличие установленных ИИ-CLI и вызывает тот, который находит, с флагом, отключающим интерактивный запрос разрешений. То, что он отправляет, стоит прочитать (здесь приведено в сокращенном виде из анализа полезной нагрузки от StepSecurity):
Это выглядит как задача, которую вполне мог бы поставить разработчик, в чем и заключается суть. Инструкция не использовать sudo — это проявление осторожности со стороны злоумышленника, поскольку запрос пароля мог бы кого-то насторожить. Агент работает от имени разработчика, имея доступ к его файловой системе, поэтому он может прочитать всё, что доступно самому разработчику.
4. Эксфильтрация
Собранные пути и содержимое файлов кодируются в base64 и отправляются в публичный репозиторий, созданный в рамках собственной учетной записи GitHub жертвы. Данные покидают систему через аутентифицированную сессию GitHub, которая уже была активна на машине.
5. Каскадный эффект
Полезная нагрузка также перехватила токены GitHub. Используя их, злоумышленники сделали приватные репозитории жертв публичными, что привело к раскрытию всех секретов, содержащихся в этих репозиториях, в дополнение к тем, что уже были украдены.
Последствия
В рамках одной автоматической установки разработчик:
- Допустил утечку всех учетных данных, находившихся в файлах .env, ~/.ssh и конфигурациях облачных сервисов
- Передал аутентифицированный токен GitHub, который стал ключом ко второй волне атаки
- Опубликовал результаты в публичном репозитории под своей учетной записью
- Столкнулся с тем, что приватные репозитории стали публичными, раскрыв секреты, которых даже не было на его машине
- Получил необходимость ротации учетных данных для всех сервисов, к которым они имели доступ
GitGuardian насчитал 2349 уникальных украденных секретов в 1079 скомпрометированных репозиториях, причем более 1100 из них оставались валидными на момент анализа. Это результат одной автоматической установки на машине, где агент и учетные данные используют общую файловую систему.
Как Docker Sandboxes ограничивает доступ к секретам
Подпись: Диаграмма, показывающая учетные данные, хранящиеся на хосте и внедряемые на границе сети, где доступ агента к файловой системе ограничен рабочей областью.
Docker Sandboxes запускают AI-агентов для кодинга в изолированных микроВМ, каждая из которых имеет собственное ядро, файловую систему и сетевую политику «запрещено по умолчанию». Таким образом, скомпрометированная зависимость, которую подгружает агент, не может получить доступ к хосту, его учетным данным или другим рабочим нагрузкам. В выпусках 1 и 2 рассматривались команды, а в выпуске 3 — сама микроВМ. Для решения проблемы секретов работают два свойства этой архитектуры.
Доступ к файловой системе в рамках рабочей области: внутри «песочницы» агент может читать только файловую систему рабочей области проекта и ничего больше. Согласно документации Docker Sandboxes, пользовательские конфигурации вне рабочей области, включая всё, что находится в домашнем каталоге, в ВМ отсутствуют. При повторении сценария s1ngularity этап разведки не дает результатов. Скомпрометированная зависимость всё еще может вызвать CLI и запросить список секретов, но файлы, которые она ищет, отсутствуют в файловой системе, доступной агенту.
Прокси-внедрение учетных данных: секреты, установленные с помощью sbx secret, хранятся в связке ключей хостовой ОС. Внутри «песочницы» агент видит только маркер-заглушку, а прокси, работающий на хосте, внедряет реальные учетные данные в исходящие запросы на границе сети. Таким образом, учетные данные никогда не попадают в ВМ, и агент не имеет доступа к их значению. Согласно документации по безопасности Docker, полностью скомпрометированная «песочница» не содержит реальных секретов для эксфильтрации.
Вам не обязательно верить на слово. Запустите временную «песочницу» и прочитайте переменную изнутри:
Вот сокращенный результат:
Внутри «песочницы» переменная является маркером, управляемым прокси, а сохраненные учетные данные GitHub отображаются как существующие, но не внедренные. Это именно тот вопрос, который запрос s1ngularity задавал каждой машине, до которой мог дотянуться. Внутри «песочницы» ответом является заглушка. Учетные данные также можно хранить вне хранилища секретов хоста. Их получение из хранилища при запуске с использованием интеграции 1Password, описанной в руководстве по рабочим процессам Docker Sandboxes, означает, что значение извлекается при старте «песочницы» и никогда не записывается на диск ни с одной из сторон границы. Я отдельно описал полную настройку, включая режимы сбоев, о которых стоит знать.
Как это выглядит на практике
Вот тот же рабочий процесс, настроенный так, чтобы учетные данные оставались на хосте.
Агент ведет себя одинаково в обоих случаях. Разница лишь в том, к чему он может получить доступ.
Лучшие практики по ограничению доступа агента к секретам
- Не передавайте агенту файлы с учетными данными. Храните секреты на хосте и внедряйте их на границе сети. Секрет, который агент никогда не видит, он не сможет закоммитить, залогировать или случайно раскрыть.
- Предоставляйте агенту доступ только к рабочей области, а не ко всей машине. Этап разведки s1ngularity сработал только потому, что агент мог прочитать всё. Уберите этот доступ, и инвентаризировать будет нечего.
- Относитесь к установленному AI CLI как к привилегированной автоматизации. Аутентифицированный агент на вашем диске — это постоянная возможность, которой может воспользоваться любой установленный вами пакет.
- Никогда не используйте флаг обхода разрешений на хосте. Если вы хотите, чтобы агент работал без подтверждения каждого шага, запускайте его внутри «песочницы». Именно граница делает пропуск разрешений безопасным.
- Читайте журнал политик. sbx policy log записывает каждое соединение, которое прокси разрешил или запретил, — это именно то, что нужно проверять после установки новой зависимости.
Действуйте
- Установите Docker Sandboxes. Посетите документацию Docker Sandboxes, чтобы установить sbx и запустить своего первого агента с доступом к файловой системе только в рамках рабочей области.
- Перенесите свои ключи на прокси-внедрение. Запуск sbx secret set, а затем sbx run — самый быстрый способ увидеть изменения на практике. Агент проходит аутентификацию в обычном режиме, а «сырой» ключ никогда не попадает в «песочницу».
- Изучите модель безопасности. Документация по безопасности Docker Sandboxes подробно описывает обработку учетных данных, уровни изоляции и сетевую политику.
Заключение
Docker Sandboxes не пытается сделать агента более осторожным с секретами, которые он видит. Она меняет то, что агент может видеть. Учетные данные остаются на хосте и внедряются только в момент выхода запроса из ВМ, а файловая система, которую читает агент, ограничена рабочей областью. Граница обеспечивается инфраструктурой, а не суждением модели, что делает её чем-то, что команда может проанализировать заранее.
В следующих выпусках нашей серии: в выпуске 5 мы рассмотрим инъекции промптов через документы и веб-контент, который читает агент, где инструкции, перенаправляющие агента, поступают внутри данных, с которыми его попросили работать.
Узнать больше
- Безопасный запуск агентов с Docker Sandboxes: посетите документацию Docker Sandboxes, чтобы начать работу.
- Исследуйте каталог Docker MCP: откройте для себя MCP-серверы, которые подключают ваших агентов к внешним сервисам через архитектуру Docker, ориентированную на безопасность.
- Скачайте Docker Desktop: самый быстрый путь к управляемой среде AI-агентов с Docker Sandboxes, MCP Gateway и Model Runner в одной установке.
- Читайте серию «MCP Horror Stories»: начните с выпуска 1, чтобы понять риски безопасности на уровне протоколов, которые дополняют риски на уровне агентов, описанные здесь.






