diff --git a/agents/.agents/skills/claude-subagent-playbook/references/codex-exec.md b/agents/.agents/skills/claude-subagent-playbook/references/codex-exec.md index ee0c76a..632b790 100644 --- a/agents/.agents/skills/claude-subagent-playbook/references/codex-exec.md +++ b/agents/.agents/skills/claude-subagent-playbook/references/codex-exec.md @@ -15,10 +15,10 @@ WSL2 Ubuntu: exec/resume/`-o`/фоновый Bash — весь конвейер) ## Сквозные правила (любая ветка) -- **Предполёт — один раз на новой машине или в новом харнессе.** Две - проверки. Песочница: диагностика из - [codex-sandbox-apparmor.md](codex-sandbox-apparmor.md) (сигнатура поломки - и лечение — там же). Вывод доходит до файла: `codex --version > f; +- **Предполёт — на новой машине, в новом харнессе и после обновления или + переустановки Codex.** Две проверки. На Linux/WSL песочница: оба режима + и границы записи по [codex-sandbox-apparmor.md](codex-sandbox-apparmor.md). + Вывод доходит до файла: `codex --version > f; wc -c f` — непусто значит, что рецепты ниже работают как написаны. Пусто: среда теряет унаследованный файловый дескриптор, и на входе, и на выходе (известный случай — T3 Code, [lessons.md](lessons.md) 2026-08-06); тогда @@ -118,14 +118,12 @@ WSL2 Ubuntu: exec/resume/`-o`/фоновый Bash — весь конвейер) `jq`, редиректы под Windows работают). `$SCRATCH` задавай forward-slash-путём (`/c/Users/...`), не `C:\...`; пути в аргументах кавычь; в выводах под Windows возможны `\r`. -- **Linux: sandbox может молча сломаться обновлением Codex.** Сигнатура: - web_search работает, а `pwd` внутри песочницы — нет - (`bwrap: loopback: Failed RTM_NEWADDR`). Обход без sudo - `use_legacy_landlock=true` чинит только read-only, write-режим с ним - паникует; полный фикс — AppArmor-профиль, и он под sudo: сам не применяй, - дай пользователю готовые команды из - [codex-sandbox-apparmor.md](codex-sandbox-apparmor.md) (`!`-префикс в чат), - после применения профиля напомни убрать `use_legacy_landlock`. +- **Linux: shell-команды падают до запуска, хотя web_search работает.** + При ошибке bwrap, в том числе `Failed RTM_NEWADDR`, сначала установи + причину и фактический способ запуска по + [codex-sandbox-apparmor.md](codex-sandbox-apparmor.md). Там же — штатная + настройка, переход со старого обхода и критерий готовности. При провале + предполёта сначала восстанови среду, затем запускай рабочие задачи. - **Блок классификатора — сначала сузь песочницу, потом зови пользователя.** Первая проверка: нет ли в команде `-s danger-full-access` — классификатор его блокирует, и он не нужен (почему — в ветке исполнителя). Если блок не diff --git a/agents/.agents/skills/claude-subagent-playbook/references/codex-sandbox-apparmor.md b/agents/.agents/skills/claude-subagent-playbook/references/codex-sandbox-apparmor.md index 655caca..7a1a4c3 100644 --- a/agents/.agents/skills/claude-subagent-playbook/references/codex-sandbox-apparmor.md +++ b/agents/.agents/skills/claude-subagent-playbook/references/codex-sandbox-apparmor.md @@ -1,120 +1,157 @@ -# Sandbox Codex на Linux: диагностика и починка (bwrap/AppArmor) +# Песочница Codex на Linux: проверка и настройка AppArmor -Справочник: симптомы, корень и рецепты фикса поломки песочницы Codex CLI -на Linux с AppArmor (эмпирика Ubuntu 24.04, 2026-07-10). Самодостаточен. +Читай при первом запуске на Linux/WSL, после смены версии или установки +Codex и при отказе команд внутри песочницы. Основной путь — системный +`bwrap` со штатным профилем AppArmor. Способ запуска проверяй по фактам: +номер версии сам по себе не доказывает выбор встроенного или системного bwrap. -## Симптом +## 1. Проверь запуск в нужной среде -Любая команда внутри sandbox Codex падает **до запуска процесса**, даже `pwd`: - -``` -bwrap: loopback: Failed RTM_NEWADDR: Operation not permitted -``` - -Проявляется и в read-only, и в workspace-write. Codex не может ни читать файлы через shell, ни выполнять команды — задачи либо виснут, либо честно завершаются отказом. - -## Корневая причина (подтверждена kernel audit log) - -**Codex CLI 0.144.1 (npm) сменил Linux-sandbox backend**: раньше был Landlock/seccomp без user namespaces, теперь — vendored bubblewrap (`…/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/codex-resources/bwrap`), который создаёт unprivileged user namespace + network namespace. - -Ubuntu 24.04 с `kernel.apparmor_restrict_unprivileged_userns = 1` загоняет такой userns в запретительный AppArmor-профиль `unprivileged_userns`, который блокирует два шага, нужных bwrap: запись `/proc/PID/uid_map` и `RTM_NEWADDR` (поднятие loopback). Доказательство из audit log: - -``` -apparmor="AUDIT" operation="userns_create" comm="bwrap" profile="unconfined" target="unprivileged_userns" -apparmor="DENIED" operation="open" name="proc/…/uid_map" profile="unprivileged_userns" denied_mask="wr" -``` - -Важные отрицательные результаты (экономят время диагностики): - -- **Плагин openai-codex (1.0.5 → 1.0.6) ни при чём** — он лишь передаёт режимы sandbox бинарю codex; даунгрейд плагина не помогает. -- Системный `/usr/bin/bwrap` падает так же — это не баг vendored-сборки. -- Система не менялась (машина без ребута 14 недель, политика AppArmor старая) — это дрейф самого Codex CLI, прилетевший с обновлением npm-пакета. - -## Применённый фикс без sudo (обратимый) - -В `~/.codex/config.toml` добавлено: - -```toml -[features] -use_legacy_landlock = true -``` - -Backup рядом: `~/.codex/config.toml.bak-20260710`. Откат — восстановить backup или удалить две строки. - -## Проверка (сквозная, через codex-companion) - -- Read-only задача `task --wait --fresh` («pwd + первая строка /etc/os-release») — команды выполняются, вернула корректные значения. -- **web_search работает**: задача сходила на github.com/openai/codex/releases. Нюанс: сетевой доступ из *shell-команд внутри sandbox* по-прежнему закрыт (`npm view` виснет) — это корректный read-only режим; инструмент web_search исполняется вне sandbox и не страдает. -- Изоляция сохранена: запись вне workspace запрещена. - -## Известное ограничение фикса - -`use_legacy_landlock` чинит **только read-only**. Режим `--write`/workspace-write с этим флагом **паникует**: - -``` -permission profiles requiring direct runtime enforcement are incompatible with --use-legacy-landlock -``` - -— workspace-write требует именно bwrap-backend. Полный фикс — ниже, нужен sudo. - -## Полный фикс (sudo; применён и проверен 2026-07-10) - -**Ловушка, съевшая первую попытку**: профиль на путь vendored bwrap -(`**/codex-resources/bwrap`) НЕ работает — Codex ≥0.144 исполняет -**встроенный** bwrap из memfd (`linux-sandbox/src/bundled_bwrap.rs`, -`memfd_create` в бинаре), и путевой attachment не цепляется никогда: в audit -виден `profile="unconfined" comm="bwrap"` → transition в -`unprivileged_userns`. Прямой запуск vendored bwrap с диска при этом -проходит — ложное подтверждение, не верь ему. - -**Рабочий вариант**: вешать профиль на **сам бинарь codex** (родителя) — -memfd-exec'нутый ребёнок наследует метку через exec, и правило `userns,` -разрешает namespace. Стандартный приём Ubuntu для браузеров/Electron. -`/etc/apparmor.d/codex-bwrap`: - -``` -abi , -include - -profile codex-cli /home/dmitry/.npm-global/lib/node_modules/@openai/codex/**/bin/codex flags=(unconfined) { - userns, - include if exists -} - -profile codex-bwrap /home/dmitry/.npm-global/lib/node_modules/@openai/codex/**/codex-resources/bwrap flags=(unconfined) { - userns, - include if exists -} -``` - -Загрузить: `sudo apparmor_parser -r /etc/apparmor.d/codex-bwrap`. После этого **убрать** `use_legacy_landlock` из config.toml и проверить оба режима: - -``` -codex sandbox -c 'sandbox_mode="workspace-write"' -- sh -c 'touch ./__p && rm ./__p && echo OK' -codex sandbox -- sh -c 'touch ./__p 2>/dev/null && echo BROKEN || echo RO_OK' -``` - -Проверено 2026-07-10: WRITE_OK, read-only блокирует запись, workspace-write -не пускает в `/etc` — изоляция сохранена. - -Переносимость: путь в профиле — под конкретную машину (`~/.npm-global/...`); glob `**` переживает обновления версий Codex, но если npm-global живёт в другом месте — путь поправить. Перезагружать профиль нужно только при смене самого расположения. - -**Вариант B — грубый, не рекомендуется**: `sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0` (+ файл в `/etc/sysctl.d/`). Ослабляет защиту всей машины. - -## Диагностические команды для другой машины +Из рабочего каталога проекта выполни оба вызова тем же способом, которым +будет запущен исполнитель или ревьюер: ```bash -codex --version # 0.144.1+ → bwrap-backend -sysctl kernel.apparmor_restrict_unprivileged_userns # 1 → будет блокировка -bwrap --ro-bind / / --unshare-net --dev /dev --proc /proc true && echo BWRAP_OK -sudo dmesg | grep -iE 'apparmor.*(userns|bwrap)' | tail # AUDIT/DENIED — подтверждение +codex sandbox -c 'sandbox_mode="read-only"' -- sh -c 'pwd && echo READ_OK' +codex sandbox -c 'sandbox_mode="workspace-write"' -- sh -c \ + 'set -eu; probe=$(mktemp ./.codex-sandbox-check.XXXXXX); rm -- "$probe"; echo WRITE_OK' ``` -## Связанные записи +Успех — нулевой код выхода и соответствующий маркер от каждой команды. +Это проверка запуска; проверка запретов записи — в разделе 4. +Работающий `web_search` ничего не говорит о выполнении shell-команд. -Принесено 2026-07-10 из ветки `codex-sandbox-fix-20260710` (исходная машина — -Ubuntu 24.04; там сжатая версия жила в codex-companion.md, который в основной -линии уже поглощён codex-exec.md). Сжатая версия урока здесь — в -[codex-exec.md](codex-exec.md), сквозное правило «Linux: sandbox может молча -сломаться обновлением Codex»; датированная запись — в -[lessons-archive.md](lessons-archive.md). +Если в конфигурации остался `use_legacy_landlock=true`, для проверочных +вызовов добавь `-c 'features.use_legacy_landlock=false'`: проверяем штатную +песочницу, а не старый обход. + +## 2. Установи причину отказа + +`bwrap: loopback: Failed RTM_NEWADDR: Operation not permitted` — повод +проверить AppArmor, но не достаточный диагноз. Собери: + +```bash +codex --version +cat /etc/os-release +type -a codex bwrap +sysctl kernel.apparmor_restrict_unprivileged_userns +cat /proc/self/attr/current +``` + +Проверь журнал ядра за время неудачного вызова: записи `apparmor="DENIED"` +для `userns_create`, `uid_map` или настройки сети подтверждают ограничение +AppArmor. Отсутствие доступа к журналу — пробел в диагностике, а не +доказательство причины. При отказе доступа к +`codex-bwrap-synthetic-mount-targets` сравни минимальный вызов из среды +агента и из обычного терминала хоста. Если на хосте он работает, исследуй +ограничения внешней песочницы и способ запуска агента; профиль AppArmor +пока не считай причиной. Если вызов падает и на хосте, а причина по +доступным данным не установлена, сохрани точную ошибку и результаты обоих +запусков; запроси недостающие записи журнала за это время. До подтверждения +причины рецепт AppArmor не применяй. + +По [документации OpenAI](https://learn.chatgpt.com/docs/sandboxing#prerequisites) +Codex выбирает первый `bwrap` из `PATH`, а при его отсутствии использует +встроенный. Проверяй `PATH` именно запускающего процесса: оболочка, +редактор и агент могут видеть разные установки. При расхождении с этим +поведением установи фактический исполняемый файл дочернего bwrap через +`/proc//exe` или трассировку `execve`/`execveat`; одного `command -v` +для этого недостаточно. + +## 3. Настрой системный bwrap + +Если подтверждена блокировка AppArmor, используй пакет `bubblewrap` и +профиль `bwrap-userns-restrict` из дистрибутива. Путь в профиле должен +соответствовать фактически запускаемому bwrap. При другой копии в `PATH` +сначала приведи запуск к системной установке. + +Для Ubuntu 24.04 официальный рецепт использует пакеты: + +```bash +sudo apt update +sudo apt install bubblewrap apparmor-profiles apparmor-utils +``` + +Если `/etc/apparmor.d/bwrap-userns-restrict` уже существует, изучи его; +локальные изменения сохрани. Если файла нет, проверь наличие штатного +образца и установи его: + +```bash +test -f /usr/share/apparmor/extra-profiles/bwrap-userns-restrict && \ + sudo install -m 0644 /usr/share/apparmor/extra-profiles/bwrap-userns-restrict \ + /etc/apparmor.d/bwrap-userns-restrict +``` + +Загрузи профиль без перезагрузки машины: + +```bash +sudo apparmor_parser -r /etc/apparmor.d/bwrap-userns-restrict +``` + +В Ubuntu 25.04 профиль поставляется пакетом `apparmor`; на других выпусках +проверь состав пакетов. Если образца нет или загрузка не удалась, останови +этот рецепт и выясни совместимость пакетов и AppArmor по документации +дистрибутива. Отсутствующий профиль не заменяй расширением разрешений всей +машины или отключением песочницы. + +Установка пакетов и изменение профилей — настройка машины. Выполняй её в +пределах уже разрешённой задачи; если настройка среды не разрешена, сначала +подготовь конкретные команды по результатам диагностики и запроси согласие. + +## 4. Проверь результат и убери старый обход + +Повтори оба вызова из раздела 1. Затем проверь границы записи, явно задавая +режим каждому вызову: + +- `read-only`: чтение работает, создание временного файла внутри проекта + запрещено. +- `workspace-write`: создание и удаление временного файла внутри проекта + работает; запись за пределами разрешённых каталогов запрещена. + +Для проверки запрета используй отдельный временный каталог, в который тот +же пользователь может записать вне проверяемой песочницы. Отказ засчитывай +только после успешного запуска команды и как запрет доступа, а не любую +ошибку. `/etc` не подходит: запись туда обычно запрещена уже правами Unix; +`/tmp` не подходит для проверки внешнего запрета, если разрешён политикой. +Удали только созданные проверкой файлы и каталоги. + +Если раньше был установлен профиль на бинарь Codex (например, +`codex-bwrap` с секциями `codex-cli*`), одного успешного прогона недостаточно: +дочерние процессы могут наследовать его разрешения. При переходе сохрани +старый профиль для отката, выведи его из автозагрузки и выгрузи его секции +из ядра. Запусти проверку из новой оболочки, не унаследовавшей старую метку +AppArmor, и новым процессом Codex. Продолжение прежней сессии не доказывает +независимость от обхода. При неудаче восстанови старую настройку и сохрани +диагноз; переход не завершён. + +Готово, когда оба режима и запреты записи проверены, а при переходе со +старого профиля — ещё и подтверждена независимость от него. После этого +убери оставшийся `use_legacy_landlock` из конфигурации. Если системная +настройка не выполнялась, различай «инструкция подготовлена» и +«песочница на этой машине исправлена». + +## Исторические обходы и границы применимости + +- **2026-07-10, Codex 0.144.1, Ubuntu 24.04.** Наблюдался запуск встроенного + bwrap через `memfd`: профиль на дисковый файл bwrap не применялся. + Профиль на сам бинарь Codex с разрешением `userns` помог. Это запасной + вариант для подтверждённого встроенного запуска, если перейти на + поддерживаемый системный bwrap нельзя; путь определяют на конкретной + машине, ограничивая его текущей установкой. +- **Тогда же:** `use_legacy_landlock=true` помогал read-only, но + workspace-write завершался ошибкой несовместимости. Для конвейера, + которому нужна запись, это не решение. +- **2026-09-10, Codex 0.154.0.** Смена npm-установки на standalone вывела + бинарь из-под старого профиля; добавление второго пути устранило симптом. + Затем этот рецепт применён на Ubuntu 24.04.4: штатный профиль из + `apparmor-profiles` 4.0.1really4.0.1-0ubuntu0.24.04.7 установлен без + изменений, старые профили Codex выгружены и убраны из автозагрузки. + Из процесса `unconfined` проверены чтение, запрет записи в read-only, + запись внутри workspace-write и запрет снаружи; перед проверкой обычная + пользовательская запись в оба временных каталога проходила. + Через `/proc` подтверждены `/usr/bin/bwrap` с меткой `bwrap (enforce)` + и дочерняя команда с `bwrap//&unpriv_bwrap (enforce)`. + `apparmor_restrict_unprivileged_userns=1` сохранён, legacy-обход отсутствует. + +Наблюдения относятся к указанным установкам, а не ко всем версиям Codex. +Штатный рецепт и состав пакетов сверены с документацией OpenAI 2026-09-10. +Связанная запись: [lessons-archive.md](lessons-archive.md). diff --git a/agents/.agents/skills/claude-subagent-playbook/references/lessons-archive.md b/agents/.agents/skills/claude-subagent-playbook/references/lessons-archive.md index 7dedab9..954f743 100644 --- a/agents/.agents/skills/claude-subagent-playbook/references/lessons-archive.md +++ b/agents/.agents/skills/claude-subagent-playbook/references/lessons-archive.md @@ -55,9 +55,9 @@ - Ревьюер Codex без read-only: мандат промптом надёжен, песочница не режется. Поглощено: codex-exec (ветка ревьюера). -- Sandbox-инцидент CLI 0.144.1 (bwrap+userns vs AppArmor) и ловушка memfd - (профиль на путь bwrap не цепляется — вешать на бинарь codex). Поглощено: - codex-exec + codex-sandbox-apparmor.md. +- Sandbox-инцидент CLI 0.144.1 (bwrap+userns vs AppArmor): при наблюдавшемся + запуске через memfd помог профиль на бинарь Codex. Актуальная настройка + и границы этого обхода — в [codex-sandbox-apparmor.md](codex-sandbox-apparmor.md). - Постановка через `/to-tickets` ложится в конвейер без трения; двойное слепое ревью постановки окупилось (Клод — механика кода, Codex — уровень требований; пересечение 2 из ~15). Поглощено: SKILL.md этапы 1–2.