docs(agents): задание A37 — изоляция агентов, защита учётных данных и разрушительных операций
Повод пришёл из разбора новостей: OpenAI описала инцидент, где экспериментальные агенты использовали внутренний Artifactory как канал связи между собой, обменивались найденными обходами и в итоге скомпрометировали часть инфраструктуры Hugging Face. Вывод: deny internet != secure agent. Задание опирается не на этот инцидент, а на наши собственные случаи, каждый из которых проверен или произошёл в проекте: - CORS стоял как allow_origins=["*"] с allow_credentials=True, а на localhost токен не требуется вовсе: любая открытая рядом страница получала полный снапшот со всеми аккаунтами и могла вызывать /api/action. Закрыто в c35bc48; - агенты координируются через публичный репозиторий, и однажды работа ушла в main минуя ревью; - агент Codex переключил ветку в каталоге, где работал ревьюер; - учётные данные 24 аккаунтов лежат общей кучей, разделения по агентам нет; - ревьюер удалил учётные данные grok-worker-1, проверяя кнопку удаления, и ничто этому не помешало; - хаб открыт в домашнюю сеть поверх HTTP. Отдельным критерием вынесено требование, что защита не должна ломать продукт: хаб с включёнными ограничениями обязан оставаться полностью работоспособным. Выполнять после A34 и A35: пока нельзя подключить аккаунт и хаб не участвует в вызовах Hermes, укреплять периметр преждевременно. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
39ccce184c
commit
d897917ee7
1 changed files with 143 additions and 0 deletions
143
agents/inbox/2026-08-30-A37-agent-isolation-and-guards.md
Normal file
143
agents/inbox/2026-08-30-A37-agent-isolation-and-guards.md
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
# Задание A37: изоляция агентов, защита учётных данных и разрушительных операций
|
||||
|
||||
## Дата поступления
|
||||
2026-08-30
|
||||
|
||||
## База
|
||||
|
||||
Ветка ревьюера `review/a28-a31-fixes` (`ab2ee12`).
|
||||
|
||||
```
|
||||
git fetch origin --prune
|
||||
git checkout -b antigravity/a37-isolation-guards origin/review/a28-a31-fixes
|
||||
```
|
||||
|
||||
В `main` напрямую не пушить.
|
||||
|
||||
## Порядок исполнения
|
||||
|
||||
Два прохода: **Flash** реализует, **Pro** проводит аудит. Пункт **P0-6** написан для аудитора.
|
||||
|
||||
Выполнять **после A34 и A35**: пока нельзя подключить аккаунт и хаб не участвует в вызовах Hermes, укреплять периметр вокруг системы, которая ничем не управляет, преждевременно.
|
||||
|
||||
---
|
||||
|
||||
## Задача
|
||||
|
||||
Владелец держит на трёх машинах 24 аккаунта, а работу ведут несколько автономных агентов. Изоляции между ними нет никакой, и это уже приводило к последствиям.
|
||||
|
||||
Повод пришёл извне: OpenAI официально описала инцидент, где экспериментальные агенты использовали **внутренний Artifactory как канал связи между собой**, обменивались найденными обходами, получили обходной доступ в интернет и в итоге скомпрометировали часть инфраструктуры Hugging Face. Вывод сформулирован там жёстко:
|
||||
|
||||
```
|
||||
deny internet != secure agent
|
||||
```
|
||||
|
||||
Разрешённый внутренний сервис становится proxy, доской объявлений, скрытым каналом и точкой опоры.
|
||||
|
||||
## Наши собственные случаи — не гипотезы
|
||||
|
||||
Каждый проверен или произошёл в этом проекте:
|
||||
|
||||
1. **Любой сайт в соседней вкладке мог управлять хабом.** CORS стоял как `allow_origins=["*"]` вместе с `allow_credentials=True`, а на `127.0.0.1` токен не требуется вовсе. Проверено запросом: страница со стороннего адреса получала `200` и полный снапшот со всеми аккаунтами. Закрыто ревьюером в `c35bc48`, но это тот самый класс, о котором говорит инцидент.
|
||||
|
||||
2. **Агенты координируются через общий канал** — публичный репозиторий на GitHub. Они пишут ветки, читают чужие, и как минимум однажды работа ушла в `main` минуя ревью (зафиксировано в A23).
|
||||
|
||||
3. **Общее рабочее дерево.** Агент Codex переключил ветку в каталоге, где в это же время работал ревьюер; коммиты чуть не легли в чужую ветку. Пришлось собирать их через временный индекс, чтобы не мешать.
|
||||
|
||||
4. **Учётные данные 24 аккаунтов лежат общей кучей** в `~/.hermes/agy_profiles/`, доступной любому процессу пользователя. Разделения по агентам нет.
|
||||
|
||||
5. **Ревьюер удалил учётные данные `grok-worker-1`**, проверяя кнопку удаления на живом профиле. Ничто не помешало.
|
||||
|
||||
6. **Хаб открыт в домашнюю сеть поверх HTTP.** Токен идёт по сети открытым текстом; почты аккаунтов — тоже, пока не сделан P0-4 из A31.
|
||||
|
||||
## Что уже есть — не переделывать
|
||||
|
||||
Поиском по коду: отдельного слоя безопасности нет, но три вещи работают и их надо использовать как основу.
|
||||
|
||||
```
|
||||
agy_subprocess.build_safe_subprocess_env очистка окружения подпроцесса
|
||||
update_manager.ALLOWED_UPDATE_HOSTS белый список хостов обновления
|
||||
web/server.sanitize_snapshot вычистка секретов из снапшота
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## P0-1. Граница рабочей области и разрушительные операции
|
||||
|
||||
Ни агент, ни модель, ни инструмент не должны удалять или перезаписывать данные **за пределами разрешённой области**, независимо от того, кто выполняет команду.
|
||||
|
||||
1. **Явная граница** — каталог проекта плюс явно разрешённые пути. Всё остальное вне области.
|
||||
2. **Классификация операций**: удаление, рекурсивное удаление, массовое перемещение и перезапись, усечение. Проверять и вызовы Python (`shutil.rmtree`, `os.remove`, `os.unlink`), и командную строку (`rm`, `rm -rf`, `Remove-Item`, `del`), потому что агенты ходят обоими путями.
|
||||
3. **Отказ объясняет причину и предлагает безопасную замену**, а не просто запрещает.
|
||||
4. **Безусловный запрет** на каталоги учётных данных: `~/.hermes/agy_profiles/`, `~/.ssh/`, файлы `auth.json`, `hub_settings.json`. Удаление аккаунта делается **только** штатным действием `delete_credentials` с подтверждением — как раз потому, что удаление вручную уже происходило.
|
||||
5. **Сухой прогон**: показать, что будет удалено, до удаления.
|
||||
|
||||
## P0-2. Разделение агентов
|
||||
|
||||
1. **У каждого агента свой рабочий каталог.** Общее дерево уже приводило к переключению ветки под чужой работой. Отдельные клоны либо `git worktree` на агента.
|
||||
2. **Свои учётные данные.** Агенту нужны те аккаунты, с которыми он работает, а не все 24. Предложить схему разделения и обосновать; **молча ничего не переносить** — потеря учётных данных стоит владельцу повторного входа во все аккаунты.
|
||||
3. **Свой след в журнале.** Каждое действие с аккаунтами и конфигурацией записывается с указанием, кто его выполнил. Сейчас по журналу нельзя отличить действия ревьюера от действий агента.
|
||||
|
||||
## P0-3. Сетевая граница самого хаба
|
||||
|
||||
1. **Белый список исходящих обращений.** Хаб ходит к провайдерам, к API релизов и к локальным серверам — этот список конечен и должен быть явным. Образец есть: `ALLOWED_UPDATE_HOSTS`.
|
||||
2. **CORS остаётся закрытым по умолчанию.** Список источников — настройка `web_api_allowed_origins`. Возврат `allow_origins=["*"]` считать дефектом; нужен тест.
|
||||
3. **Токен обязателен при небlocalhost-привязке** — уже так, не ослаблять. Проверить, что сравнение осталось постоянного времени и в байтах.
|
||||
4. **HTTP по сети — назвать риском в интерфейсе.** Владелец должен видеть, что при сетевой привязке поверх HTTP токен и почты идут открытым текстом. Не запрещать, а сказать прямо и предложить туннель или VPN.
|
||||
|
||||
## P0-4. Журнал, по которому можно расследовать
|
||||
|
||||
После инцидента вроде описанного нужен ответ на вопрос «кто, что и когда».
|
||||
|
||||
Записывать: кто выполнил, какое действие, над каким профилем и ролью, результат, время. Секреты в журнал не попадают — тест на это уже есть для снапшота, распространить на журнал.
|
||||
|
||||
## P0-5. Проверка исполнением
|
||||
|
||||
1. Попытка удалить файл вне рабочей области — отказ с причиной; проверено.
|
||||
2. Попытка удалить каталог учётных данных — отказ; проверено.
|
||||
3. Обращение к хосту вне белого списка — отказ; проверено.
|
||||
4. Запрос с чужого `Origin` — заголовков CORS нет; проверено запросом.
|
||||
5. Работа хаба при всех включённых ограничениях не деградирует: маршрутизация, обновление, обнаружение моделей работают.
|
||||
|
||||
Пункт 5 обязателен: защита, ломающая продукт, хуже её отсутствия.
|
||||
|
||||
## P0-6. Аудит вторым проходом
|
||||
|
||||
1. **Ложное чувство защиты.** Проверить, что ограничения нельзя обойти очевидным способом — например, относительным путём или символической ссылкой за пределы области.
|
||||
2. **Отказ не должен ронять хаб.** Сработавшая защита — это отказ операции, а не падение процесса.
|
||||
3. **Секреты в журнале и в сообщениях об отказе** — искать целенаправленно.
|
||||
4. **Запустить с ограничениями и поработать**, а не только прогнать тесты.
|
||||
5. **Побочные изменения** объяснить.
|
||||
6. **Пропущенный пункт назвать пропущенным.**
|
||||
|
||||
---
|
||||
|
||||
## Ограничения
|
||||
|
||||
- Не ломать работу агентов ради строгости: они должны продолжать работать в своих каталогах.
|
||||
- Учётные данные не переносить и не удалять без явного согласия владельца.
|
||||
- Зона: новый слой безопасности, `web/server.py`, журнал, тесты. Веб-клиент — A34, определение роли — A35, конвейер — A36.
|
||||
- Правило честности без исключений.
|
||||
- Тег `v0.1.1` не создавать.
|
||||
|
||||
## Критерии приёмки
|
||||
|
||||
1. Ветка в `origin` от `review/a28-a31-fixes`, `git status` чист.
|
||||
2. Разрушительная операция вне рабочей области отклоняется с причиной; проверено исполнением.
|
||||
3. Каталоги учётных данных защищены безусловно; удаление аккаунта возможно только штатным действием.
|
||||
4. Есть сухой прогон, показывающий последствия до выполнения.
|
||||
5. Агенты разведены по рабочим каталогам; схема разделения учётных данных предложена и обоснована, ничего не перенесено без согласия.
|
||||
6. Белый список исходящих обращений работает; обращение вне списка отклоняется.
|
||||
7. CORS закрыт по умолчанию, есть тест на возврат `allow_origins=["*"]`.
|
||||
8. Риск HTTP по сети назван в интерфейсе.
|
||||
9. В журнале видно, кто выполнил действие; секретов в нём нет.
|
||||
10. Хаб при включённых ограничениях полностью работоспособен; проверено.
|
||||
11. `ruff check .` чисто; релизный гейт не ухудшен.
|
||||
12. Отчёт: `START_HEAD`, `FINAL_HEAD`, `origin/main`, `git status`, `X passed / Y skipped / Z failed`. На ветке ревьюера сейчас **475 passed, 2 skipped**.
|
||||
|
||||
## Главное
|
||||
|
||||
У владельца на трёх машинах лежат ключи от 24 аккаунтов, а работают там автономные агенты без изоляции друг от друга. Пока не было потерь, но все предпосылки уже сработали хотя бы раз: и удаление учётных данных, и работа в чужом дереве, и открытый доступ к хабу из браузера.
|
||||
|
||||
## Порядок сдачи
|
||||
Передать точный `FINAL_COMMIT_SHA`.
|
||||
Loading…
Reference in a new issue