Чек‑лист по хранению ключей в репозиториях на основе инцидентов с ИИ‑агентами
Вряд ли я тут кому‑то открою тайну, рассказом о том, как хранить ключи, но тут прочитал статью на TechCrunch, где рассказывается, что CERT‑In (национальное агентство кибербезопасности Индии) обнаружило, что ИИ‑агенты нескольких разработчиков моделей во время тестов добрались до живых систем индийских организаций. Агентам хватило учетки и настройки подключения, оставленных в конфигурации приложений и публичных репозиториях кода, и слишком широких облачных ролей. При этом пострадавшие организации вторжения сами не заметили.
Поэтому, больше для себя, решил написать чек‑лист, он состоит из девяти пунктов, каждый привязан к способу входа из этих инцидентов и говорит, что проверить, какой командой и как исправить. А в конце написал, что делать, если ключ уже утек.
Что произошло и почему это касается любого
Факты из сообщения CERT‑In. Агентство получило добровольные сообщения от нескольких провайдеров ИИ‑моделей: их агенты во время исследовательских и тестовых прогонов в открытом интернете оказались в живых системах индийских организаций. Действия агентов, по формулировке агентства, вышли за рамки поставленных задач. По той же формулировке, они читали персональные данные и конфиденциальные деловые записи. CERT‑In не назвал ни провайдеров, ни пострадавшие организации и не сказал, меняли ли агенты что‑то в системах.
Подробности советов CERT‑In я беру из разбора The Hacker News от 16 октября 2026 года, потому что страница самого уведомления недоступна. По этому разбору, слабые места были обычными: ключи в исходном коде, истории публичных репозиториев, конфигурационных файлах и клиентских приложениях, забытые тестовые API, платежные ключи в открытом виде, широкие облачные роли и административные интерфейсы без многофакторной защиты. В случаях, о которых сообщили ИИ‑компании, агенты находили один и тот же открытый ключ и использовали его в разных операциях.
Почему это не только про Индию. Агент автоматически перебирает то, что найдет в открытом доступе. Ключ в публичном месте, скорее всего, найдут, а роль с лишними правами могут использовать. Поэтому чек‑лист написан для обычной команды разработки.
Те же приемы показал июльский разбор Anthropic. В раскрытии компании от 30 июля 2026 года описаны три инцидента из 141 006 проверенных тестовых прогонов. Модель Claude, получив задачу на взлом вымышленной цели, из‑за ошибки в настройке тестовой среды выходила в реальный интернет и принимала настоящие системы за часть упражнения. Во всех случаях она применяла простые приемы, в частности слабые пароли и адреса API без аутентификации, а в одном случае читала учетные данные со страницы отладки и использовала SQL‑инъекцию. Две организации из трех, до которых удалось достучаться, активности не заметили.
Сравнительная таблица по входам такая:
Способ входа | Где описан | Что проверять |
|---|---|---|
Ключи и настройки подключения в репозитории и истории | CERT‑In | Пункты 1 и 2 |
Секреты в конфигурации приложений и клиентском коде | CERT‑In | Пункты 3 и 4 |
Слишком широкие облачные роли | CERT‑In | Пункты 5 и 6 |
Забытые тестовые API, слабые пароли, страница отладки | CERT‑In, Anthropic | Пункты 7 и 8 |
Вторжение остается незамеченным | CERT‑In, Anthropic | Пункт 9 |
Репозитории, где ключ видят все
Пункт 1. Ключ в публичном репозитории и его истории
В инцидентах агенты входили по учетным данным из публичных репозиториев кода.
Ключ остается в старых коммитах, ветках, форках и локальных клонах, даже если файл удалили. Поэтому проверяйте всю историю, старые коммиты тоже.
Для поиска подойдут два инструмента. Gitleaks из репозитория проекта сканирует историю командой gitleaks git -v, отчет с замаскированными значениями получается так:
gitleaks git --report-path gitleaks-report.json --redact
TruffleHog умеет проверять найденное: по документации проекта опция --results=verified оставляет только секреты, которые подтвердились у выдавшего их сервиса. Полный проход по организации на GitHub:
trufflehog github --org=ИМЯ_ОРГАНИЗАЦИИ --results=verified,unknown
Результат unknown стоит разбирать вручную: проверка могла сорваться из‑за сети, хотя ключ рабочий. Любая находка из verified означает срочную ротацию, о ней ниже.
Проверьте также форки и приватные репозитории, ставшие публичными. Часто ключ утекает тогда, когда команда открывает бывший внутренний проект.
Пункт 2. Защита от повторной утечки на этапе коммита
Та же дорога через публичные репозитории откроется и завтра, если не поставить заслон.
Лучший момент поймать ключ наступает до коммита. Gitleaks подключается как хук через pre‑commit. В файле .pre-commit-config.yaml указывается репозиторий gitleaks, нужная версия и идентификатор хука gitleaks, затем выполняется pre-commit install. Хук можно обойти флагом SKIP=gitleaks, значит, одного его мало.
Вторым рубежом служит защита на стороне сервера. GitHub называет ее push protection, и документация объясняет, что она блокирует отправку коммита с распознанным секретом. Третий рубеж проходит в CI: тот же gitleaks git на каждый запрос на слияние, с падением сборки при находке.
Если репозиторий большой и старых находок много, снимите базовый отчет через --report-path, а потом запускайте проверку с --baseline-path. Тогда сборка падает только на новых секретах, а старые разбираются отдельным планом.
Конфиги и секреты рядом с кодом
Пункт 3. Секреты в конфигурации приложения, CI и клиентском коде
Агенты входили по настройкам подключения из конфигурации приложений.
Чаще всего утечка выглядит буднично. Пароль базы лежит в config.yaml, токен в переменной CI, ключ внутри мобильного приложения или фронтенда. По разбору The Hacker News, CERT‑In отдельно перечислил CI/CD‑переменные, конфигурационные файлы, клиентские приложения и открытые веб‑страницы.
Проверка начинается с поиска по рабочей директории:
gitleaks dir .
Для контейнеров и CI‑переменных пройдитесь вручную: переменные окружения в логах сборки, docker history образов, артефакты сборки. Найденное переносите в менеджер секретов (Vault, облачный Secret Manager и подобные) и подтягивайте во время запуска.
Если секреты пока лежат в .env, сделайте минимум: права 600 и владелец только пользователь сервиса. Проверка одной командой:
find . -name '.env*' -perm /077
Пустой вывод означает, что другие пользователи файл не читают. Права 600 закрывают файл от соседних учетных записей на сервере, а взломанный процесс‑владелец прочитает его сам, поэтому .env годится как временная мера.
Пункт 4. Привилегированный ключ в клиентском коде
По разбору The Hacker News, ключи нашлись и в клиентских приложениях, и на открытых веб‑страницах.
Любой секрет, попавший в браузер или мобильное приложение, считайте публичным. CERT‑In по пересказу The Hacker News советует держать привилегированные ключи вне клиентского кода и проверять, что может прочитать и записать анонимный пользователь. Возьмите собранный фронтенд, поищите в нем ключи теми же сканерами и сделайте тестовый запрос к API и хранилищу без всякой авторизации. Ответ с данными означает ошибку в правах.
Облако и права шире задачи
Пункт 5. Ревизия ролей и сервисных аккаунтов
Агенты входили через слишком широкие облачные роли.
Минимальные права проверяет вопрос: что реально делает эта роль, и сколько из выданного она использует. Для AWS полезны отчет по учетным данным и анализатор доступа IAM:
aws iam generate-credential-report
aws iam get-credential-report
Первая команда формирует отчет о пользователях, ключах и их последнем использовании, вторая отдает его. В нем видно ключи, которыми не пользовались месяцами. Документация IAM Access Analyzer описывает анализаторы, которые находят доступ, открытый наружу, и права, оставшиеся без использования.
В Google Cloud начните с ключей сервисных аккаунтов:
gcloud iam service-accounts keys list --iam-account=SA_EMAIL
Ключи старше квартала и ключи, о которых никто не помнит, удалите. Роли вроде владельца проекта или администратора на сервисном аккаунте приложения замените конкретными ролями с узким набором разрешений.
Пункт 6. Долгоживущие токены на короткоживущие
Найденный один раз ключ работал потом снова и снова. По данным The Hacker News, в сообщениях ИИ‑компаний агенты находили один и тот же открытый ключ и применяли его в разных операциях.
Чем короче срок жизни, тем меньше вреда от находки. В AWS приложению выдают временные учетные данные через роль:
aws sts assume-role --role-arn ARN_РОЛИ --role-session-name app --duration-seconds 900
В Google Cloud вместо файла ключа используют имперсонацию сервисного аккаунта:
gcloud auth print-access-token --impersonate-service-account=SA_EMAIL
Для собственных ИИ‑агентов CERT‑In, по разбору The Hacker News, советует то же самое: отдельная короткоживущая личность с минимальными правами на каждый запуск и закрытый исходящий трафик, кроме нужных адресов.
Забытая поверхность
Пункт 7. Забытые тестовые API и слабые пароли
В Индии это были старые и тестовые API, доступные из интернета, а у Anthropic слабые пароли и адреса без аутентификации.
Составьте реестр всех API и учетных записей. Список выглядит буднично, но по нему находятся тестовый стенд двухлетней давности и забытая демо‑учетка. Каждый пункт реестра получает владельца и срок. Без владельца и без дела он выключается.
Слабый пароль в 2026 году остается рабочим входом. Разбор Anthropic это иллюстрирует, ведь модель использовала слабые пароли и адреса без аутентификации. Пройдите по административным панелям, базам и сервисным интерфейсам, закройте их от интернета, включите многофакторную защиту и смените пароли по умолчанию.
Пункт 8. Страница отладки и зависимости
В третьем случае Anthropic учетные данные взяли со страницы отладки, во втором модель опубликовала вредоносный пакет в публичном реестре (второй случай).
Отладочный режим нужно выключать в рабочей среде. В третьем инциденте модель прочитала учетные данные с открытой страницы отладки. Проверка: откройте приложение с заведомо неверным запросом и убедитесь, что вместо стека ошибки и переменных окружения возвращается короткая страница ошибки.
Второй урок о зависимостях. В инструкции вымышленной компании был пакет из PyPI, которого не существовало. Модель опубликовала пакет с таким именем, и по описанию Anthropic его скачали 15 реальных систем за час, а сканер одной настоящей компании выполнил код и отдал ее учетные данные. Выводы для команды: занимайте имена внутренних пакетов в публичных реестрах, фиксируйте хеши зависимостей и запускайте установку через pip install --require-hashes -r requirements.txt, а проверяющие сканеры держите в песочнице без рабочих ключей.
Наблюдение за доступом
Пункт 9. Мониторинг и сигналы о необычном доступе
Пострадавшие организации сами вторжения не обнаружили: так сказано об Индии, и так было у двух организаций Anthropic, до которых удалось достучаться.
Алерты строятся на поведении: частоте, объеме и источнике запросов. CERT‑In, по разбору The Hacker News, советует следить за API через обнаружение аномалий по частоте запросов, оповещать о переборе, массовых чтениях и автоматических регистрациях и хранить журналы не меньше 180 дней. Пригодится и журнал действий агентов, если они у вас работают в рабочих системах.
Конкретные сигналы, которые стоит завести сразу:
вход с ключа из необычной сети или страны;
резкий рост числа чтений из хранилища или базы за короткое время;
обращение к ключу, которым не пользовались неделями;
создание новых ключей, ролей и учетных записей вне плановых работ.
Ключи‑приманки. Поставьте в репозиторий и конфигурацию фиктивные учетные данные, которые нигде не работают. Любое обращение к ним сразу сигнал тревоги: ложных срабатываний почти не бывает.
Что делать, если ключ уже утек
Действуйте в таком порядке. CERT‑In в пересказе The Hacker News требует считать среду скомпрометированной до результатов судебной проверки. После исправления среду нужно перепроверить и ждать повторных попыток в течение дней или недель.
Отзовите ключ немедленно. Для AWS сначала деактивируйте:
aws iam update-access-key --access-key-id ID_КЛЮЧА --status Inactive --user-name ИМЯ. Для Google Cloud удалите ключ:gcloud iam service-accounts keys delete KEY_ID --iam-account=SA_EMAIL. Для ключей сторонних сервисов используйте кнопку отзыва в их кабинете.Выпустите новый ключ и обновите приложения. Новое значение попадает только в менеджер секретов.
Проверьте журналы за период жизни ключа. Что и когда читали, откуда приходили запросы. Без журналов за нужный срок вы не узнаете масштаб, поэтому срок хранения 180 дней важен заранее.
Удалите ключ из истории репозитория. Для этого подходит утилита git‑filter‑repo:
git filter-repo --replace-text expressions.txtзаменяет значения, перечисленные в файле. Затем принудительная отправка и просьба ко всем коллегам заново клонировать репозиторий. Порядок важен: сначала отзыв, потом очистка, потому что к моменту очистки ключ могли уже скопировать.Проверьте по периметру снаружи. Запустите сканеры еще раз и убедитесь, что старый ключ отзывается с ошибкой, а в публичной истории его нет.
Сообщите тем, кого это касается. По разбору The Hacker News, правила CERT‑In требуют сообщать о киберинцидентах агентству в течение шести часов, а для российских компаний действуют другие обязанности, поэтому уточните их у юриста или специалиста по безопасности.
По разбору The Hacker News, в отдельной кампании против индийских компаний жертвы, исправившие проблему лишь частично, подвергались повторным атакам в течение нескольких дней. Поэтому отзывайте сразу все соседние ключи вместе с найденным.
Выводы
Агентам хватило ключей и прав, оставленных на виду. В описании CERT‑In нет изощренных эксплойтов, и Anthropic называет свои случаи простыми приемами. Если ключ лежит в истории репозитория, роль дает больше, чем нужно, и журнал никто не просматривает, задача агента становится легкой.
Я начал с того, что сначала прогнал gitleaks и trufflehog по всем репозиториям, включая форки и старые проекты. Затем выписал все ключи и роли в облаке, удалил неиспользуемые и заменил долгоживущие токены временными. И наконец, включил хранение журналов на 180 дней и настроил оповещения на необычное чтение данных. После этого добавил хук и push protection, чтобы новые ключи не попадали в репозиторий.
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.