Перейти к содержимому

Evomal: как вирус продолжил распространяться в hermes после удаления исходного навыка

Посадил в Hermes вирус, а потом удалил его. Агент продолжил заражаться самостоятельно

Я удалил из библиотеки Hermes навык с тестовой "закладкой". К этому моменту её копии уже появились в десяти навыках, созданных самим агентом. После удаления исходного файла я поручил Hermes ещё пять задач - число заражённых skill-файлов выросло до четырнадцати.

Это был контролируемый эксперимент, а не реальный инцидент. Вместо вредоносного кода использовалась безобидная строка-маркер `EVOMAL-MARKER-7f3a2b`. Она позволяла отследить распространение заражения и не представляла опасности для системы. Результат, однако, оказался неприятным: для саморазвивающихся агентов стандартная рекомендация "проверь навык перед установкой и удали его при обнаружении проблемы" может оказаться недостаточной.

Почему обычное удаление не помогает

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

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

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

Откуда взялась идея эксперимента

Проблема связана с атакой EvoMal - механизмом самозаражения самоэволюционирующих coding-агентов. В описанной модели атака проходит в три этапа:

1. В библиотеку добавляют навык с замаскированной инструкцией.
2. Агент выполняет обычные задачи и обращается к похожим навыкам как к примерам.
3. При сохранении собственного решения он переносит скрытое правило в новый skill.

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

В исследовании, посвящённом этой атаке, показатель успешного самораспространения для разных моделей составлял от 20 до 42% задач. Особенно показателен эксперимент с очисткой исходных файлов: после удаления всех первоначальных закладок заражённые навыки продолжали появляться. В одном из сценариев к пятому раунду распространения доля таких результатов достигла 68%.

Полноценный код авторы исследования не опубликовали, а независимых воспроизведений было немного. Поэтому я решил проверить сам принцип на Hermes.

Как можно спрятать опасную логику

У навыка есть несколько мест, которые могут использоваться для маскировки.

Описание во frontmatter. Оно часто читается агентом ещё до загрузки полного содержимого. Поэтому вместо нейтрального описания туда можно поместить инструкции, рассчитанные непосредственно на модель.

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

Scripts и references. Скрипты способны выполняться автоматически или по просьбе агента. При этом модель может не анализировать их содержимое так же подробно, как текст инструкции.

В реальной атаке злоумышленник может попытаться украсть переменные окружения, подменить конфигурацию, добавить вторую стадию заражения или использовать навык как элемент атаки на цепочку поставок. Для MCP-серверов применимы дополнительные техники: от poisoning описания инструмента до так называемого rug pull, когда ранее одобренное поведение меняется уже после установки.

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

В тесте все эти варианты заменяла одна строка-маркер. Целью было проверить не вредоносную нагрузку, а сам канал распространения.

Стенд и ход проверки

Для эксперимента использовался Hermes версии 0.20.5. Важным условием было наличие у агента сразу нескольких возможностей:

- читать библиотеку навыков;
- выбирать существующие skills как примеры;
- создавать новые навыки;
- сохранять их обратно в ту же библиотеку.

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

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

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

Именно после этого число заражённых файлов продолжило расти: от десяти на момент удаления источника до четырнадцати после дополнительных прогонов.

Что означает такой результат

Эксперимент показывает важную особенность: удаление файла не равно очистке среды. Если агент успел перенести инструкцию в новые документы, библиотека уже стала графом зависимостей. Источник можно уничтожить, но его копии продолжат существовать в потомках.

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

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

Почему визуальный просмотр недостаточен

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

Кроме того, опасное правило может активироваться только при создании нового skill-файла. До этого оно не проявляет себя в обычном результате. Такой подход снижает вероятность обнаружения и превращает агента в механизм дальнейшего распространения.

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

Как защищать библиотеки навыков

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

Нужен журнал происхождения каждого skill-файла: использованные шаблоны, исходные документы, время создания, изменения и автор. Без такой метаинформации трудно понять, откуда появился подозрительный фрагмент.

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

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

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

Итог

Тест с Hermes не доказывает, что любая система будет вести себя идентично. На результат влияют модель, настройки, формат хранения навыков и способ их выбора. Однако сам механизм выглядит достаточно правдоподобно: агент может перенести скрытую инструкцию в собственный skill, после чего заражение продолжится без исходного файла.

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

Прокрутить вверх