Переменные среды в Codex: как не передать секреты в команды агента

Когда Codex запускает команду, человек обычно смотрит на саму команду: тесты, сборка, скрипт, проверка сайта, запуск CLI. Но у команды есть второй слой доступа, который легко не заметить. Это переменные среды.

На рабочей машине в них могут жить токены, ключи облаков, настройки API, пути к профилям, временные credentials и флаги, которые меняют поведение инструментов. Если агент запускает subprocess и тот наследует слишком много среды, безобидная команда получает больше доступа, чем нужно задаче.

Поэтому в Codex есть отдельная настройка shellenvironmentpolicy. Ее смысл простой: решить, какие переменные Codex передает командам, которые сам запускает, а какие должны остаться за границей.

Почему переменные среды становятся невидимым доступом

Файл проекта виден. Команду видно в терминале. А переменная среды часто остается в фоне. Она не выглядит как "доступ", пока через нее не начинает работать внешний сервис.

Например, тестовая команда может не требовать облачного ключа. Сборка сайта может не требовать личного токена. Скрипт проверки ссылок может не требовать доступа к платежной системе. Но если среда наследуется целиком, эти значения могут оказаться рядом с командой просто потому, что они были настроены на машине.

Для Codex это особенно важно: агент не просто пишет текст, он может запускать команды и читать вывод. Значит, нужно заранее отделить рабочие переменные от секретов.

Что именно регулирует shellenvironmentpolicy

Официальная документация Codex описывает shellenvironmentpolicy как настройку, которая контролирует, какие переменные среды передаются subprocess-командам, запускаемым Codex. Документация предлагает начинать с чистого режима inherit = "none" или с урезанного inherit = "core", а затем добавлять include/exclude/override-правила.

Практически это выглядит так:

Режим Что означает Когда уместен
inherit = "all" Команда получает много из текущей среды Только в доверенной, отдельно подготовленной среде
inherit = "core" Передается ограниченный базовый набор Когда нужны обычные пути и системные настройки
inherit = "none" Почти ничего не наследуется автоматически Когда важнее всего не протащить секреты
include_only Разрешены только названные переменные Для понятного pass list перед рабочими командами
exclude Отдельные паттерны запрещены Для блокировки облачных ключей и токенов

В документации также есть важная защитная идея: имена с KEY, SECRET и TOKEN по умолчанию относятся к чувствительным. Это не магическая защита от всего, но хороший сигнал: секреты не должны попадать в командную среду случайно.

Что дать Codex на вход

Не просите Codex просто "настроить безопасно". Дайте ему список фактов.

Вот команды, которые Codex должен запускать: тесты, сборка, локальный smoke-check. Вот переменные, которые им нужны: PATH, HOME, NODEENV. Вот что нельзя передавать subprocess-командам: любые значения с KEY, SECRET, TOKEN, облачные credentials и личные API-ключи. Собери карту shellenvironment_policy и объясни, как ее проверить.

Такой вход переводит безопасность из ощущения в артефакт. Codex должен вернуть не философию, а список: что наследуем, что включаем, что исключаем, что остается ручным.

Какой артефакт должен получиться

Хороший результат — это маленькая карта среды.

В ней должны быть:

  • режим наследования: none, core или другой обоснованный вариант;
  • разрешенный список переменных;
  • запрещенные паттерны;
  • команды, для которых эта политика подходит;
  • команды, которые нельзя запускать в этом профиле;
  • место, где человек утверждает исключения.

Если Codex предлагает "просто оставить как есть", это слабый результат. Смысл политики как раз в том, чтобы не оставлять все как есть.

Как проверить список без программирования

Непрограммисту не нужно понимать все переменные. Достаточно пройтись по списку глазами.

Первый вопрос: есть ли в разрешенном списке слова KEY, SECRET, TOKEN, PASSWORD, CREDENTIAL, названия облаков или платежных сервисов?

Второй: может ли команда выполнить задачу без этих значений?

Третий: есть ли отдельное место, где описано, кто может добавить исключение?

Если секрет нужен только для установки зависимостей, публикации или доступа к внешнему сервису, это не значит, что он должен быть доступен каждой команде агента. Иногда правильное решение — отдельный профиль, отдельный runner или ручной шаг.

Где человеческое решение остается обязательным

Codex может предложить карту, но не должен сам решать, какие секреты ему можно открыть. Это решение владельца процесса.

Человек определяет:

  • какие команды достаточно безопасны для обычного профиля;
  • где нужна отдельная среда;
  • какие переменные вообще нельзя передавать агенту;
  • когда секрет должен жить только в secret manager;
  • кто отвечает за ротацию и отзыв доступа.

Политика переменных среды не заменяет sandbox, approvals, MCP/app permissions и нормальное хранение секретов. Она закрывает один конкретный слой: что получит команда, которую Codex запускает из shell.

Практическая карточка: pass list переменных среды

Перед тем как давать Codex запускать команды в проекте, заполните короткую карточку.

Команды: что Codex может запускать сам.

Нужные переменные: что этим командам действительно требуется.

Разрешенный список: что можно передавать всегда.

Запрещенные паттерны: KEY, SECRET, TOKEN, облачные ключи, платежные credentials, личные токены.

Исключения: кто и когда может разрешить дополнительную переменную.

Проверка: команда работает без лишних секретов, а результат можно принять человеком.

Так Codex получает достаточно среды, чтобы работать, но не получает все, что случайно оказалось на машине. Это спокойный, взрослый режим: агент запускает команды, а границы доступа остаются видимыми.