Если Codex CLI на удалённом Mac видит соседний репозиторий, оставляет процесс после разрыва SSH или получает доступ к ключу подписи, запуск нельзя считать принятым.

Самое быстрое решение: не размещайте Agent в общей высокопривилегированной учётной записи; сначала создайте отдельного системного пользователя, изолируйте рабочую область каждого репозитория, включите минимальный sandbox и подтверждения, а затем проведите проверки файлов, сети, учётных данных, Xcode и восстановления. Если границы не доказаны, переходите на временный узел для одного репозитория или на двухконтурный CI.

Эта статья для профессиональных разработчиков, которым нужно поручать Codex CLI изменение, сборку или тестирование нескольких репозиториев на удалённом Mac. Она также нужна DevOps-инженерам, сопровождающим постоянно работающие узлы, и специалистам по безопасности, проверяющим доступ Agent к исходному коду, Keychain, подписи и инструментам Xcode.

Сначала определите допуск: общий узел против отдельного контура

Проблема не в том, способен ли Codex CLI запуститься на macOS. Критический вопрос — может ли процесс выйти за пределы ожидаемой рабочей области, использовать права системной учётной записи или передать задачу внешнему исполнителю. В документации OpenAI sandbox, стратегия подтверждений и сетевой доступ описаны как отдельные элементы контроля выполнения, поэтому их нельзя заменять одной настройкой или правилом в системном промпте (описание sandbox и подтверждений Codex).

Используйте такую схему допуска:

  • Можно запускать в общем удалённом Mac-контуре, если у каждого задания есть отдельная системная учётная запись либо эквивалентная подтверждённая граница, рабочие каталоги не пересекаются, сетевые запросы журналируются, а производственные секреты выдаются временно.
  • Можно запускать ограниченно, если кодовая база изолирована, но нет доказательств полной очистки, восстановления или поведения внешних инструментов. В этом случае разрешайте только тестовые репозитории и операции без подписи и публикации.
  • Нужно отложить запуск, если Agent работает под общим администратором, видит домашний каталог другого пользователя, получает постоянный SSH Agent или использует неизвестный MCP-исполнитель.
  • Нужно перейти на отдельный узел, если после сбоя остаются процессы, файлы, токены, кэш или изменения за пределами задания.

Важное ограничение: подсказка «изменяй только этот репозиторий» не является системной границей. Она может уточнить намерение, но не отменяет права процесса читать соседние каталоги или запускать доступные команды.

Перед тестами сохраните базовый снимок: системная учётная запись, рабочий путь, права каталогов, переменные окружения, активные агенты ключей, доступные связки Keychain, процессы и сетевые правила. Секреты в снимок не включайте — фиксируйте только факт наличия и назначение.

Первая метрика: файлы и репозитории

Проверка файловой изоляции должна отвечать не на вопрос «работает ли сборка», а на вопрос «какие данные процесс фактически может прочитать и изменить». В область контроля входят:

  • корень рабочей директории;
  • соседние каталоги и родительский путь;
  • .git, worktree и служебные файлы;
  • конфигурация проекта и локальные скрипты;
  • временный каталог, кэш и DerivedData;
  • журналы, артефакты и файлы, созданные внешними инструментами.

Создайте два тестовых репозитория с нейтральными маркерами и отдельные файлы-приманки за пределами рабочей области. Используйте заполнители вроде <REPO_A>, <REPO_B>, <TEST_USER> и <WORKSPACE_PATH>. Не помещайте туда ключи, токены, сертификаты или реальные персональные данные.

Затем выполните проверку в такой последовательности:

  1. Запустите задачу для <REPO_A> под выделенной учётной записью.
  2. Попросите выполнить безопасную операцию внутри рабочего каталога и зафиксируйте изменённые файлы.
  3. Проверьте попытку чтения маркера из <REPO_B> и родительского каталога.
  4. Проверьте попытку создать файл за пределами <WORKSPACE_PATH>.
  5. Сравните состояние обоих репозиториев, временных каталогов и логов.
  6. Повторите сценарий после переключения на <REPO_B>.

Проход означает, что чтение и запись ограничены ожидаемым корнем, а временные артефакты либо находятся в выделенном каталоге, либо удаляются по завершении. Остановка обязательна при успешном чтении соседнего маркера, изменении чужого Git-дерева, записи в домашний каталог администратора или сохранении неизвестного файла после очистки.

Рабочая область и сетевой доступ — разные метрики. Даже если файл нельзя записать, команда может попытаться отправить его через разрешённое соединение. Поэтому файловый тест не заменяет сетевой.

Вторая метрика: сеть и внешние исполнители

Разделите сетевые действия по назначению: обмен с моделью, загрузка зависимостей, операции Git, обращение к API проекта и выполнение внешним инструментом. Фраза «подтверждения отключены» не означает, что сеть включена или ограничена. В конфигурации Codex поля разрешений и режимы sandbox нужно сверять с актуальными официальными материалами, а не с примером из старого сообщения (исходный файл конфигурации Codex с полями разрешений).

Проверка должна включать:

  • запрос к разрешённому адресу зависимости;
  • попытку обращения к неразрешённому адресу;
  • Git-операцию через ожидаемый хост;
  • обращение к API с тестовым маршрутом;
  • запуск команды через MCP или другой внешний исполнитель;
  • запись решения о разрешении, отказе и ошибке.

Для каждого запроса укажите ожидаемый результат: разрешить, отклонить, потребовать подтверждение или записать событие для последующего анализа. Не ограничивайтесь проверкой браузера или VNC-сессии: проверяется сеть процесса и его дочерних команд.

В официальном описании разрешений OpenAI отдельно рассматриваются режимы подтверждения и границы выполнения (документация Codex по разрешениям). Практический вывод для удалённого Mac простой: сетевое правило должно быть воспроизводимым, а не зависеть от того, какой текст Agent сформулировал в очередной задаче.

Проверьте также путь через MCP. Если внешний исполнитель получает собственные права, доступ к сокету или возможность запускать команды вне локальной sandbox-модели, его нужно оценивать как отдельный доверенный компонент. Сообщения в GitHub Issues могут подсказать, что следует перепроверить, но отдельный отчёт сообщества нельзя автоматически объявлять общей уязвимостью (пример обсуждаемого отчёта сообщества Codex).

Объект проверки Тестовое действие Условие допуска Условие остановки
Модельный сетевой обмен Выполнить задачу без доступа к проектным API Запросы соответствуют утверждённому маршруту Неожиданный внешний адрес
Зависимости Загрузить тестовую зависимость Разрешён только необходимый источник Произвольный выход в сеть
Git Выполнить чтение и отправку в тестовый репозиторий Учётные данные и хост ожидаемы Доступ к другому хосту или репозиторию
MCP / внешний исполнитель Запустить безопасную диагностическую команду Права и журналирование явно определены Обход локальной границы

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

Третья метрика: учётная запись, SSH Agent и Keychain

Права Codex CLI нельзя оценивать только по настройкам самого CLI. На результат влияют системный пользователь macOS, группы, переменные окружения, SSH Agent, login keychain и доступные сертификаты. Apple описывает управление доступом приложений к данным Keychain отдельно от обычных файловых разрешений, поэтому наличие файла конфигурации не доказывает отсутствие доступа к связке ключей (руководство Apple по авторизации доступа к Keychain).

Проведите три режима проверки:

  1. Без учётных данных. Удалите или отключите тестовые ключи и проверьте, не видит ли процесс их имена, агент или связку.
  2. Только чтение. Выдайте временный доступ к тестовому ресурсу и проверьте, может ли задача использовать его только для разрешённой операции.
  3. Временный секрет. Разрешите действие с тестовым токеном, затем отзовите его и проверьте, не остаётся ли копия в окружении, логах, кэше или процессе.

Для SSH проверяйте не только каталог ключей, но и переменную SSH_AUTH_SOCK, список добавленных ключей и поведение дочерних процессов. Команды в документации и журнале заменяйте заполнителями: <SSH_SOCKET>, <TEMP_TOKEN>, <TEST_CERTIFICATE>. Не показывайте реальные значения, отпечатки производственных ключей или Team ID.

Производственный ключ подписи, сертификат публикации и постоянный ключ доступа к репозиторию нельзя предоставлять обычной сессии Agent. Если сборка требует подписи, разделите этапы: Codex CLI изменяет код и запускает непроизводственную проверку, а отдельный контролируемый процесс выполняет подпись после ревью. Это снижает последствия ошибочной команды, но не отменяет отдельную проверку прав.

Четвёртая метрика: Xcode, команды и параллельность

Успешный xcodebuild показывает, что команда выполнилась, но не доказывает воспроизводимость и изоляцию. Для тестового проекта проверьте:

  • откуда читаются исходники и конфигурация;
  • куда записываются DerivedData и архив;
  • какие скрипты запускаются из Scheme;
  • какие Simulator и локальные сервисы используются;
  • пересекаются ли порты, кэши и журналы двух заданий;
  • остаются ли процессы после завершения или отмены.

Используйте заполнители <SCHEME_NAME>, <BUILD_PATH>, <DERIVED_DATA_PATH> и <SIMULATOR_ID>. Сначала запускайте задачи последовательно, затем — только если среда это допускает — проверяйте параллельность на независимых рабочих каталогах. Сравните контрольные признаки: файлы, созданные процессы, кэш, логи и состояние Simulator.

Область Что сравнивать до и после Решение при расхождении
Рабочее дерево git diff, новые и удалённые файлы Остановить общий запуск
DerivedData и кэш Владельца, путь и принадлежность заданию Разделить каталоги
Simulator Устройство, состояние и артефакты Выделить Simulator или запускать последовательно
Скрипты Scheme Команды и внешние пути Проверить каждую команду отдельно
Параллельные задания Порты, процессы, логи и временные файлы Перейти на пул отдельных узлов

Не объявляйте параллельность безопасной только потому, что оба задания завершились успешно. Признаком отказа является даже небольшая перекрёстная запись: общий лог, чужой кэш, неправильный архив или изменение файла другого репозитория.

Пятая метрика: очистка и восстановление после сбоя

Узел для длительных задач проверяется не только в рабочем состоянии. Введите сценарии отказа: нормальное завершение Codex CLI, принудительный выход, разрыв SSH, отмена сборки, перезагрузка Mac и переключение на другой репозиторий. Для каждого сценария заранее зафиксируйте ожидаемое состояние.

Проверяйте:

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

После перезагрузки не возвращайте Mac в общий пул автоматически. Сначала повторите базовый снимок и сравните учётную запись, права, активные процессы, сетевые правила, Keychain и рабочие каталоги. Если автоматическая очистка не может доказать отсутствие остатка, безопаснее пересоздать временный контур, чем пытаться «дочистить» неизвестное состояние.

Сроки контрольных точек

В день подготовки создайте тестовые репозитории и матрицу разрешённых действий. До первого пилота завершите файловую, сетевую и credential-проверку. До допуска Xcode-задач отдельно подтвердите пути DerivedData, Simulator и подпись. Перед постоянной эксплуатацией выполните сценарии разрыва SSH, выхода Agent и перезагрузки.

При изменении модели разрешений Codex CLI, sandbox, режима MCP, большой версии macOS или версии Xcode повторите проверку. Даже без такого изменения плановый пересмотр нужен не реже одного раза в квартал: это условие процесса контроля, а не утверждение о производительности или стабильности конкретного узла.

Условия выбора: общий узел, временный Mac или двухконтурный CI

Используйте решение по условиям, а не бинарную метку «безопасно».

  • Если отдельный системный пользователь, рабочая область, сетевые правила, временные учётные данные и очистка подтверждены журналами, то можно допустить несколько репозиториев с ограниченными действиями.
  • Если файловая изоляция подтверждена, но восстановление или внешний исполнитель не проверены, то выберите один репозиторий на временный узел.
  • Если нужен Xcode build без производственной подписи, но нельзя доказать отсутствие доступа к Keychain, то оставьте Agent на этапе изменения и тестовой сборки, а подпись вынесите в отдельный контур.
  • Если разные команды требуют постоянных сетевых маршрутов, ключей и кэшей, то разделите узлы по доверенным группам вместо общего Mac.
  • Если после сбоя остаются процессы, секреты или файлы, то остановите запуск, пересоздайте узел и повторите приёмку.
  • Если требуется физический интерфейс, постоянная высокая нагрузка или строго фиксированное локальное хранилище, то сравните аренду с собственной инфраструктурой и не принимайте удалённый узел автоматически.

Для короткого изолированного пилота можно изучить доступные варианты аренды удалённого Mac у VMSPIN. Если требуется сначала сопоставить срок использования и расходы, используйте страницу тарифов VMSPIN, но решение о запуске принимайте только после собственного теста прав и восстановления.

Что должно войти в акт приёмки

Акт не должен состоять из фразы «Agent работает». В него включите:

  • идентификатор тестового узла и системной учётной записи;
  • снимок разрешений до запуска;
  • список тестовых репозиториев и заполнителей;
  • результаты чтения и записи за пределами рабочей области;
  • сетевые решения и журналы внешних исполнителей;
  • состояние SSH Agent, Keychain и тестовых сертификатов;
  • результаты xcodebuild, Simulator и скриптов;
  • список процессов и файлов после каждого сценария отказа;
  • результат перезагрузки;
  • ответственное лицо и срок следующей проверки.

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

Общий удалённый Mac удобен тем, что сразу даёт macOS, Xcode и постоянную среду, но совместное использование создаёт три слабых места: пересечение рабочих каталогов, накопление долгоживущих учётных данных и сложное восстановление после ошибочной команды. Покупка Mac mini устраняет часть сетевой зависимости, однако требует самостоятельных затрат на обслуживание, доступность, резервирование и безопасное удалённое подключение. Для краткого пилота или временной CI-задачи аренда Mac через VMSPIN может быть рациональнее, если вы заранее принимаете узел по этому чек-листу и не передаёте Agent производственные ключи без отдельного контура.

Начните с непроизводственного репозитория, оформите доказательства по пяти группам и только потом решайте, нужен ли вам один узел с ротацией, отдельные Mac для доверенных команд или двухконтурная CI-схема. Для заказа тестовой среды можно перейти к вариантам удалённого Mac VMSPIN, но успешная оплата не заменяет проверку изоляции, очистки и восстановления.