Навык 33 из 40
HS-CTX-005-SECRETSУправление секретами при работе с AI-агентами
Для локального проекта с AI-агентом определить, какие секреты действительно нужны задаче, выбрать способ их хранения и доставки по модели угроз, выдать процессу минимальный набор значений и независимо проверить, что секреты не попали в Git, инструкции, промпты, логи, diff, артефакты или ответы агента. Зафиксировать владельца, область действия и способ ротации каждого секрета и после работы отозвать либо очистить ненужный доступ.
Человек различает хранение секрета и его доставку процессу. Приватный Git-репозиторий не считается хранилищем секретов: обычный .env с реальными значениями не коммитится, а в репозитории остаётся только безопасный .env.example. Для простого локального сценария значения хранятся в исключённом из Git .env.local, а контролируемый .envrc явно загружает разрешённые файлы через direnv, например сначала dotenv_if_exists .env, затем dotenv_if_exists .env.local. Такое поведение является принятой конфигурацией проекта, а не автоматическим свойством любого .envrc.
Для постоянных локальных credentials предпочтительно хранение в pass: .envrc содержит только обращения к именованным записям и экспортирует необходимое значение после осознанного direnv allow. direnv управляет project-scoped окружением, но не является sandbox: экспортированный секрет доступен разрешённому процессу и его дочерним процессам, а агент с shell-доступом потенциально может его прочитать.
git-crypt рассматривается как специальный способ хранить ограниченное число зашифрованных файлов в Git, когда это оправдано совместным или offline-сценарием. Он не ограничивает агента после git-crypt unlock, не скрывает имена и часть метаданных и не обеспечивает отзыв уже выданного доступа к прошлой истории. Выбор между .env.local, pass и git-crypt принимается по требованиям восстановления, совместной работы, отзыва, ротации и фактической границе доступа, а не по удобству одной команды.
Тренажёр навыка
Понять.
Сделать.
Подтвердить.
Что нужно уметь
Для локального проекта с AI-агентом определить, какие секреты действительно нужны задаче, выбрать способ их хранения и доставки по модели угроз, выдать процессу минимальный набор значений и независимо проверить, что секреты не попали в Git, инструкции, промпты, логи, diff, артефакты или ответы агента. Зафиксировать владельца, область действия и способ ротации каждого секрета и после работы отозвать либо очистить ненужный доступ.
Человек различает хранение секрета и его доставку процессу. Приватный Git-репозиторий не считается хранилищем секретов: обычный .env с реальными значениями не коммитится, а в репозитории остаётся только безопасный .env.example. Для простого локального сценария значения хранятся в исключённом из Git .env.local, а контролируемый .envrc явно загружает разрешённые файлы через direnv, например сначала dotenv_if_exists .env, затем dotenv_if_exists .env.local. Такое поведение является принятой конфигурацией проекта, а не автоматическим свойством любого .envrc.
Для постоянных локальных credentials предпочтительно хранение в pass: .envrc содержит только обращения к именованным записям и экспортирует необходимое значение после осознанного direnv allow. direnv управляет project-scoped окружением, но не является sandbox: экспортированный секрет доступен разрешённому процессу и его дочерним процессам, а агент с shell-доступом потенциально может его прочитать.
git-crypt рассматривается как специальный способ хранить ограниченное число зашифрованных файлов в Git, когда это оправдано совместным или offline-сценарием. Он не ограничивает агента после git-crypt unlock, не скрывает имена и часть метаданных и не обеспечивает отзыв уже выданного доступа к прошлой истории. Выбор между .env.local, pass и git-crypt принимается по требованиям восстановления, совместной работы, отзыва, ротации и фактической границе доступа, а не по удобству одной команды.
Как закрепить
В учебном репозитории составить карту «секрет → владелец → назначение → потребитель → область действия → источник → ротация и отзыв». Создать безопасный .env.example, правила .gitignore и версионируемый .envrc без значений. Настроить явную загрузку .env и .env.local через direnv, подтвердить порядок переопределения и показать trust gate direnv allow. Затем перенести один синтетический canary из .env.local в pass, заменить значение в .envrc обращением к именованной записи и проверить запуск разрешённого процесса.
Отдельно на синтетических данных разобрать два альтернативных решения: отклонить commit обычного .env в приватный remote и объяснить сохранение секрета в Git history; настроить git-crypt для учебного .env, проверить зашифрованное представление в Git и показать, что после unlock тот же файл доступен агенту как plaintext. Завершить практику поиском canary в tracked-файлах, истории, diff и подготовленных логах, очисткой окружения и демонстрацией ротации либо удаления учебного секрета.
Как проверить перенос
За 75 минут получить новый изолированный репозиторий и четыре сценария: одиночная локальная разработка, постоянный credential в password store, совместный offline-доступ и ошибочно закоммиченный .env в приватный remote. Fixture содержит .envrc, который не загружает ожидаемые файлы, конфликт значений между .env и .env.local, лишний секрет для другого сервиса, синтетический canary в одном небезопасном следе и ограниченного AI-агента с shell-доступом.
Без готовой последовательности действий участник должен выбрать и обосновать способ для каждого сценария, исправить конфигурацию direnv, реализовать один вариант через .env.local и один через pass, проверить trust gate и фактическое окружение разрешённого процесса, объяснить границу git-crypt до и после unlock, обнаружить небезопасный Git-след и выполнить безопасную ротацию canary. Проверка заканчивается отрицательным тестом: агент не получает лишний секрет, а нужное значение не появляется в его инструкции, ответе, diff или журнале.
Результат, а не ощущение
Evidence
освоения
- карта секретов с владельцем, назначением, потребителем, областью действия, источником и процедурой ротации или отзыва;
.env.example,.gitignoreи версионируемый.envrcбез секретных значений;- явная конфигурация
direnv, загружающая.envи.env.localв принятом порядке, и зафиксированный результатdirenv allow; - работающий локальный вариант с исключённым из Git
.env.local; - работающий вариант
pass + direnv, в котором в проекте хранится только ссылка на именованную запись; - сравнительное решение по обычному
.envв приватном Git,.env.local,git-cryptиpassс учётом восстановления, совместной работы, ротации и отзыва; - проверка ciphertext в Git и plaintext-доступа после
git-crypt unlockна синтетическом canary; - поиск canary в tracked-файлах, истории, diff, логах и артефактах с устранением найденного следа;
- отрицательный прогон, подтверждающий отсутствие лишнего секрета у агента;
- доказанная ротация или удаление учебного credential и очистка ненужного окружения.
Антипаттерны
Типовые ошибки
- commit реального
.envпотому, что репозиторий приватный; - предположение, что любой
.envrcавтоматически загружает.envи.env.local; - размещение значений секретов непосредственно в версионируемом
.envrc; - commit
.env.local, базыpass, GPG private key или ключаgit-cryptвместе с проектом; - применение
direnv allowбез просмотра изменённого.envrc; - восприятие
direnvкак sandbox или ACL, хотя переменные доступны процессу и его потомкам; - выдача агенту всего окружения пользователя вместо минимального набора project-scoped значений;
- вывод о безопасности
git-cryptтолько по ciphertext в remote без проверки plaintext послеunlock; - попытка отозвать доступ к уже клонированной Git history без ротации самих credentials;
- вывод секрета через
env, отладочную печать, trace, лог команды, prompt или ответ агента; - поиск утечки только в текущем файле без проверки staged state, истории и артефактов;
- диагностика на реальном токене вместо синтетического canary.