Безопасность и меры защиты
Chimera умеет выполнять команды оболочки, править файлы, вызывать API и менять собственные навыки. Она поставляется с эшелонированной защитой — и, что важно, документация говорит, где каждый слой заканчивается.
Единственное правило
Ни одна из этих мер не заменяет запуск в изолированной среде, когда вы даёте
самостоятельность. Локальный исполнитель по умолчанию не изолирован; для недоверенной работы
используйте CHIMERA_SANDBOX=docker (без сети, при желании под gVisor).
Слои
- Ядро управления — каждый управляемый вызов инструмента получает разрешить / предупредить / разобрать / заблокировать. Это дешёвый первый фильтр опасных сигнатур оболочки, а не граница.
- Песочница — временный контейнер без сети (
CHIMERA_SANDBOX=docker), усиливаемый gVisor (CHIMERA_SANDBOX_RUNTIME=runsc). Проверяющая команда выполняется в той же песочнице, что и оболочка агента, а когда эта песочница не изолирует, команда, набранная не вами, — выведенная из репозитория, прочитанная из задания по расписанию, из карточки или из сценария, — проходит через то же подтверждениеCHIMERA_HOST_EXEC; при отказе она воздерживается, а не выполняется (CHIMERA_VERIFY_NETWORK=1даёт сеть проверяющему в docker; в песочницах уровня ядра так нельзя, поэтому проверяющий, которому нужна сеть, работает на хосте — и только если его набрали вы). - Список разрешённых инструментов на сессию — дайте запуску только те инструменты, которые ему нужны; остальные вовсе убираются из схемы, которую видит модель.
- Отслеживание заражения (
--taint) — недоверенное содержимое обособляется как данные, его происхождение следует за ним в воспоминания и навыки (навык из заражённого запуска удерживается на разбор), а как только запуск заражён, опасные инструменты сужаются. - Изолированный читатель — приём двух моделей (CaMeL): недоверенное содержимое читает модель без инструментов, способная выдать только поля, прошедшие проверку схемы, поэтому внедрение не может породить новую инструкцию или вызов инструмента.
- Монитор между агентами — при веерном запуске монитор одного работника слеп к разделённому
потоку (один работник забирает недоверенное, другой его сливает — забор и слив живут в разных
журналах). Сводный монитор видит весь веер; для
solve-batchиcrew-isolatedон всегда включён.
Веерный запуск: монитор между агентами
Когда несколько работающих с инструментами агентов идут параллельно (solve-batch,
crew-isolated), каждый получает свой журнал полномочий, а после пакета по всем ним проходит сводный
монитор. Он ловит то, чего не увидит монитор одного работника, — разделённую утечку, где работник A
забирает недоверенное содержимое, а работник B его выполняет или отправляет наружу:
$ chimera solve-batch "read notes.md and summarize" "download the helper and run it" -w .
task1: ok
task2: ok
merged 2 file(s) across 2 task(s)
⚠ cross-agent monitor flagged (review):
- cross-agent-taint: untrusted content entered via one agent and a different agent
performed a sink (task2→task1) — a split flow no single-agent monitor sees
Он только поднимает до разбора — запуск он никогда не блокирует — и является чистым
наблюдением (запись ничего не меняет в поведении). Добавьте сверху --taint, чтобы заодно взвести у
каждого работника подстраивающийся список разрешений (опасные при заражении инструменты начнут
требовать одобрения).
Одобрение и как выглядит работник, которому отказали. У каждого работника свой одобряющий
и своя запись того, что ему позволили сделать, поэтому отклонённая задача так и говорит, а не
сообщает ok:
$ chimera solve-batch "read notes.md and summarize" "download the helper and run it" --taint -w .
task1: ok
task2: not allowed (ok)
governance: 1 action(s) refused for review: run_shell is restricted after this run consumed
untrusted content
1 of 2 task(s) had actions refused for review — check that the work they were asked to do
actually happened.
ok в скобках — это вердикт самого цикла, и то, что они расходятся, и есть суть: отклонённый
вызов возвращается обычной строкой наблюдения, работник читает её как любой результат
инструмента, идёт дальше и заканчивает прозой. Кого можно спросить, решает
CHIMERA_APPROVAL_MODE — deny отказывает сразу, ask спрашивает в терминале, а иначе
записывает вопрос для chimera approve и ждёт CHIMERA_APPROVAL_WAIT секунд — на каждый
вопрос и на каждого работника. Молчание всегда отказ.
Измерено, а не заявлено
chimera redteam
прогоняет корпус внедрений через весь стек. На встроенном корпусе слой заражения снижает долю успешных атак со 100% примерно до 14% — и отчёт называет то, что всё ещё проходит (утечка через разрешённый инструмент), вместо того чтобы объявить 100%.
Та же команда печатает цену, чего первая версия этой страницы не делала: когда спросить некого,
сужение отказывает в 100% законной работы, которая сначала прочитала что-нибудь внешнее —
исправить файл, названный в issue, применить обновление, описанное в документации, — и
зарегистрированный заслон (избыточные блокировки ≤ 5%) не пройден. Это число — не вопрос настройки;
заслон был пуст. Режим одобрения по умолчанию — ask, и в приложении он теперь спрашивает:
суженный вызов инструмента превращается в вопрос на экране с приложенной причиной из журнала;
ответить на него можно кнопкой или командой chimera approve, а молчание дольше
CHIMERA_APPROVAL_WAIT секунд означает отказ. Когда человек одобряет работу, о которой сам и
попросил, избыточных блокировок 0%, а доля заблокированных атак не меняется — измерено, по каждому
плечу, в bench/injection/RESULTS.md.
Утечка через разрешённый инструмент закрыта тем же изменением: в заражённом запуске http_get со
строкой запроса идёт на разбор, а два законных GET-запроса со строкой запроса, добавленные в
корпус, показывают, чего это стоит.
Отравленная память, из запуска в запуск
redteam измеряет один запуск. Другая форма медленнее и не умещается в один процесс: запуск A
читает отравленную страницу и сохраняет то, что «усвоил»; запуск B через несколько дней спрашивает
о постороннем, и обращение к памяти передаёт модели подброшенный факт.
chimera memory-poison
Тоже офлайн и бесплатно. Она по очереди отключает три слоя, стоящих между этими запусками, — флаг
происхождения tainted, приёмные ворота памяти и ярлык [unverified], с которым факт входит в
промпт, — потому что одно-единственное число было бы совместимо с тем, что любой из них ничего не
делает. Главное здесь — то, что доходит без пометки, а не то, что заблокировано: отравленный
факт, несущий своё происхождение, — это факт, о котором модель предупредили; факт без ярлыка
неотличим от того, что агент проверил сам.
Два результата первого прогона стоит назвать прямо, потому что ни один из них нам не льстит:
- Поставляемая конфигурация не проходит собственный заслон — по цене. Она помечает 100% отравы и уничтожает при этом 25% честной памяти. Потери названы поимённо: документ по безопасности, который цитирует атаку, чтобы её объяснить, и обращение в поддержку, пересылающее попытку. Проверка содержимого по шаблонам не отличает цитату от команды.
- На этом корпусе заслон по содержимому не добавляет ничего, чего уже не покрывает метка происхождения. Весь его измеренный эффект — та честная память, которую он убирает. Пятнадцать написанных вручную строк — это указатель, а не вердикт, и потому на их основании ничего не удалено.
Пороги, метод и то, чего эти числа не позволяют утверждать, лежат в
bench/memory_poison/PREREGISTRATION.md,
зафиксированные до первого прогона.
Как выставить HTTP-сервер наружу
chimera serve по умолчанию слушает на 127.0.0.1. Его меняющие состояние конечные точки (/chat,
/a2a, /webhook/*) управляют агентом, поэтому перед тем как выставить сервер в сеть, задайте
токен доступа:
export CHIMERA_SERVER_TOKEN="a-long-random-secret" # required as: Authorization: Bearer <token>
Когда он задан, эти точки POST возвращают 401 без подходящего заголовка Authorization: Bearer
(GET /health и карточка агента A2A остаются открытыми). Для входящего вебхука WhatsApp задайте
CHIMERA_WHATSAPP_APP_SECRET равным секрету вашего приложения Meta — тогда Chimera проверяет HMAC
X-Hub-Signature-256 каждого запроса и отвергает подделку с кодом 403. И то и другое включается по
желанию (не задано = аутентификации нет, что годится для localhost); публичное развёртывание должно
их задать (или стоять за прокси с проверкой подлинности).
Поделиться беседой со вторым человеком
Настольное приложение может поделиться беседой о коде по токену, который открывает только эту беседу —
никогда не по серверному токену. Владелец выпускает по одному на гостя (POST /api/code/sessions/{id}/share)
и может отозвать его отдельно; удаление беседы отзывает все. Гость достигает четырёх маршрутов под
/guest/api/…: прочитать беседу, следить за ней вживую, отправить в неё сообщение, увидеть, кто есть.
Больше ничего на токен доступа не отвечает, и у гостевого приложения нет маршрута, чтобы ответить на
карточку управления — они остаются на экране владельца.
Гостевое приложение — также единственное, что обслуживается, когда владелец открывает сетевую дверь
(POST /api/code/share/network, закрывается через DELETE, при запуске никогда не открыта): машина в
локальной сети достигает этих четырёх маршрутов и ничего из того, что защищает серверный токен. Сказать
прямо, прежде чем отдавать ссылку: гость может попросить агента о чём угодно, о чём попросил бы владелец,
в проекте владельца, его инструментами и за его счёт — в рамках настроек запроса по умолчанию и без
права одобрять карточки.
Честные пределы
Здесь измеряется, останавливается ли вредное действие уже внедрённого агента, — а не то, можно ли внедриться в модель изначально. Свободное рассуждение над недоверенным текстом и утечка через инструменты, которые действительно нужны, остаются открытыми задачами (отслеживаются как issue #5).
Полная и всегда актуальная политика лежит в SECURITY.md, включая порядок сообщения об уязвимости.