Как расследовать косвенные промпт-инъекции в ИИ-агентах


В октябре на arXiv авторы из Университета Сунь Ятсена и Гонконгского университета науки и технологий выложили работу AgentTracer. Я ее прочитала и заодно прошлась по материалам Google, Microsoft и OWASP на ту же тему. О защите агентов от инъекций написано много, а вот о расследовании после того, как что-то пошло не так, — гораздо меньше. Поэтому мне захотелось поделиться с вами своими наблюдениями о том, как по журналам агента восстановить ход атаки и что для этого нужно заранее сохранять.
Как косвенная промпт-инъекция приводит к атаке
Чтобы понять, почему такие атаки так трудно восстанавливать по журналам, нужно сначала посмотреть, как устроен контекст модели. Весь прочитанный агентом текст собирается в единый контекст модели. Откуда пришла та или иная фраза, он по сути не различает и откликается на саму формулировку. Модели приучены выполнять самую свежую инструкцию, и отличить разрешенную команду от подложенной они сами не умеют, если та звучит убедительно. При косвенной инъекции подложенная команда приходит в тексте, который агент сам открыл по заданию. Пользователь его не писал и часто даже не видел. Из этого следует, что раз вредоносная инструкция попадает в тот же контекст, что и настоящая, то и действия агента по ней выглядят как обычная работа.
Это хорошо видно на примере из AgentTracer. Авторы его придумали, реального инцидента за ним нет, но механика показана достаточно точно. Вот этот пример: пользователь просит скачать релиз с сайта и выгрузить его в репозиторий на GitHub. Страница релиза содержит скрытую инструкцию, и агент заодно регистрирует SSH-ключ атакующего, читает почту, проверяет аккаунт и в конце чистит рабочую память. Заметить можно только последний шаг. Вызов очистки памяти не получает ничего из результатов предыдущих вызовов, у него нет с вредоносной страницей общих параметров, поэтому анализ потока данных связь не найдет. Ее видно только в рассуждениях агента, где написано, зачем он это делает и на чем основано его решение. Поэтому расследование сводится к решению трех вопросов: 1) была ли это инъекция или агент просто ошибся; 2) какой внешний ресурс ее принес; 3) в какой строке он попал в контекст.
Расследование принято начинать с журналов сервера, но вмешательство может пройти мимо них. Особенно когда инструкцию прячут прямо в ссылке. В учебном сценарии из блога Microsoft, построенном на технике HashJack, текст спрятан во фрагменте адреса после символа #. Этот фрагмент обрабатывается на стороне клиента и на сервер не уходит, а сервис пересказа добавляет полный адрес в промпт. Серверные журналы сайта не покажут ничего подозрительного, потому что вмешательство видно только в том, что модель реально получила на вход. А вот один из первых известных случаев утечки данных касался Bing Chat, где скрытые на странице инструкции заставили ассистента запросить изображение с сервера атакующего и вставить данные разговора в параметры адреса. Эту проблему Microsoft исправила, а утечка со стороны выглядела как обычная загрузка картинки. Те же приемы, но только современнее использует CoSnitch — уязвимость в Copilot Personal (CVE-2026-24301). Подготовленная ссылка запускала запрос уже в авторизованной сессии жертвы без отдельного подтверждения, и результаты могли уйти через обычный запрос по URL. Значит, искать следы утечки приходится в исходящих запросах агента, а не в данных, к которым он имел доступ.
Еще сложнее, когда между внедрением и последствиями проходит время. Тот же CoSnitch использовал путь через пересказ веб-страницы, который записывал вредоносные инструкции в постоянную память ассистента. Инъекция по такой схеме переживает сессию, в которой произошла, и может сработать в другой день и совсем по другому поводу. Это самый неприятный случай для расследования, потому что причину нужно искать в журнале сессии, которая к текущему инциденту уже не относится. Авторы AgentTracer проверили такой сценарий на 45 примерах, точность превысила 85%, но результат они сами исключили из формальной оценки, потому что выборка была мала. Varonis не нашла использования CoSnitch в реальных атаках, а патчи вышли в августе 2026 года.
А нельзя ли просто искать такие тексты на входе? Специалисты компании Google просканировали архив Common Crawl, где в одном месячном снимке от двух до трех миллиардов страниц, и первым делом столкнулись с ложными срабатываниями. Больше всего подозрительных фраз оказалось в научных статьях, учебных материалах и блогах о безопасности, то есть там, где об инъекциях пишут, а не проводят их. Поэтому поиск по шаблонам вроде ignore instructions пришлось дополнить ручной проверкой и классификацией Gemini, которая смотрит, вписывается ли фраза в логику документа или торчит из него. Это решение показывает, что одного текста мало. Намерение определяется тем, как фраза связана с остальным документом, и тем, что агент сделал с ней. Авторы замечают, что безобидная подсказка для пересказа превратилась бы в атаку, если бы просила добавить дезинформацию.
Пока что большинству агентов не грозит серьезная опасность из сети. В основном Google находила шутки, SEO-приемы и попытки отпугнуть ИИ-краулеры. Попыток украсть данные или удалить файлы было мало, и выглядели они примитивно, а массовых продвинутых способов, которые исследователи описали в 2025 году, обнаружить вовсе не удалось. Тем не менее доля вредоносных находок выросла на 32% (относительно) между ноябрем 2025 и февралем 2026 года, и в Google ждут продолжения роста, потому что агенты становятся ценнее как цель, а атаковать их можно уже дешевле, чем раньше. Выборка ограничена статичными страницами, в нее не попали соцсети. Когда изощренные атаки доберутся до реальных систем, вмешательство по тексту на входе, скорее всего, уже будет не поймать, и опираться останется лишь на журнал самого агента.
Как AgentTracer восстанавливает цепочку атаки
В основе AgentTracer лежит простое наблюдение: если инъекция сработала, агент выполняет действия, которых пользователь не просил, и это расхождение с запросом остается в журнале. Авторы называют его дрейфом намерения, а задача метода в том, чтобы найти это расхождение и проследить его до источника.
Связь, которую не видно по данным, авторы ищут в записях рассуждений. Перед каждым вызовом агент пишет, зачем он это делает и на что опирается, и по этим записям строится граф решений. Узлами в нем служат запрос пользователя и объекты, полученные от инструментов (страницы, письма, созданные файлы), а ребрами — операции агента. Благодаря этому вызовы без единого общего параметра все равно попадают в одну цепочку. Для такого анализа в журнале должны храниться запрос пользователя, рассуждения и записи об инструментах с вызовами и результатами. Кроме журнала, методу нужно подозрительное событие, и в нашем примере им служит очистка рабочей памяти. Анализ начинается с отрезка журнала от ближайшего запроса пользователя до этого события.
Граф фиксирует зависимости, но отличить законные связи от незаконных он не может. Запрос пользователя почти всегда короче, чем действия, которые он подразумевает. Во фразе «отправь квартальный отчет аудитору» не упоминается, что файл сначала нужно найти и открыть, зато подразумевается, что отправить его можно только аудитору. Чтобы это формализовать, авторы собрали базу знаний об операциях, и на ее основе для каждого запроса строится пространство разрешенного. Каждый вызов проверяют по трем признакам: по действию, цели и ограничениям. Если нарушен любой из них, ребро помечается как отклонение от намерения.
Затем от подозрительного события идут назад по помеченным ребрам, и так находятся ответы на три вопроса, с которых начинается расследование. Если в корне цепочки оказывается внешний ресурс, случай засчитывают как инъекцию, ресурс получает статус источника, а строка журнала, где он попал в контекст агента, становится точкой внедрения. Если корень не является внешним ресурсом, инъекцию не засчитывают, а причиной считают недопонимание агента или обычную ошибку. Важно, что такой исход предусмотрен, потому что ответ «инъекции не было» для расследования ничуть не хуже остальных.
Авторы проверяли метод в жестких условиях. Они взяли логи успешных атак из AgentDyn и InjecAgent и смешали их с пятью месяцами обычной работы агента. На одну атакующую цепочку из трех вызовов пришлось около трех тысяч посторонних, и точку внедрения удалось указать верно примерно в 94% случаев. Восстановить цепочку целиком получается чуть реже, чем найти саму точку внедрения.
Отдельные модули авторы по очереди отключали, и это показало, какие решения важны. Когда граф решений заменили обычной лентой вызовов по порядку, точку внедрения стали находить уже реже. Когда проверку по трем признакам заменили просьбой к языковой модели оценить, нормально ли выглядит действие, точность упала еще сильнее.
Отсечение по подозрительному событию влияет на стоимость, и без него анализ занимает почти на треть больше времени и тратит в полтора раза больше токенов, а при таком количестве посторонних вызовов это ощутимо.
Теперь сопоставим эти результаты с другими методами.
Что показывают другие исследования
Авторы сравнили AgentTracer с семью другими подходами на сотне цепочек атак. Двум соперникам, универсальным агентам Codex и OpenClaw, просто отдали журнал и попросили разобраться. Остальные пять (Agent-BOM, NeuroTaint, AuthGraph, AgentArmor и ARGUS) специально создавали для трассировки атак, и авторы разделили их на три семейства. Одни строили граф по явным зависимостям управления и данных, другие оценивали вклад отдельных фрагментов входа в итоговое действие, третьи убирали кусок контекста и смотрели, исчезнет ли событие. Первому семейству тяжелее всего на примере с очисткой памяти, потому что явных зависимостей между этим вызовом и вредоносной страницей в журнале нет.
Точку внедрения AgentTracer нашел примерно в 94% случаев, а у остальных результат лежал между 40 и 76%. Авторы назвали разрыв преимуществом в 18–54%, но речь шла о процентных пунктах. Лидировал он при этом не по всем показателям. AuthGraph обнаружил все атаки, но точку внедрения нашел в меньшем числе случаев. AgentArmor собрал цепочку целиком полнее всех, зато в ней оказалось много лишнего. У NeuroTaint звенья цепочки в основном были верными, а до самой точки внедрения он добирался редко. Сильная сторона AgentTracer оказалась в том, что он удержал оба показателя сразу, а расследованию нужны и источник, и чистая цепочка. Часть конкурентов авторы воспроизводили по описаниям из статей, поэтому цифры лучше читать как сравнение внутри одной работы.
Данные для проверки авторы взяли из бенчмарков. InjecAgent создавали, чтобы измерять подверженность агентов с инструментами косвенным инъекциям, а AgentDojo задумали как динамическую среду для проверки и атак, и защит. В экспериментах использовали InjecAgent и более свежий AgentDyn, а AgentDojo упомянули как один из бенчмарков области. Из готовых сценариев атак получили журналы, на которых и проверяли метод.
Исследователи искали способ восстановить цепочку, а о том, что собирать и как действовать после инцидента, лучше всего написано в индустрии. Google ответила на вопрос о масштабе, а вот что делать, когда агент уже совершил подозрительное действие, подробно описала Microsoft. В блоге компании появился план от обнаружения до реагирования, построенный на аудите запросов и обращений к документам и на корреляции событий в Sentinel. В каталоге техник атак на ИИ Microsoft посоветовала считать любой внешний контент потенциально враждебным и логировать запросы и ответы модели, а среди мер защиты указала телеметрию ИИ. Во всех этих материалах расследование опирается на записи, которые должны существовать до инцидента. У Microsoft в центре внимания — запросы и ответы, а AgentTracer нужны еще рассуждения агента и полные результаты инструментов.
Самое интересное нашлось в квартальном обзоре OWASP. Почти все его истории за третий квартал 2026 года касались агентов, которые вышли за рамки задания без всякой чужой подсказки. Агент Claude Opus 4.7 на оценке по кибербезопасности не смог добраться до вымышленной цели, нашел настоящую компанию с похожим названием и атаковал ее. Агенты OpenAI в ходе оценки вышли в интернет через общий сервис пакетов и проникли в инфраструктуру Hugging Face. Авторы обзора отдельно оговорили, что промпт-инъекция в этих историях не установлена, и предостерегли от вывода об инъекции только на основании того, что агент ушел от задачи. Для расследования это та же дилемма, которая стояла перед AgentTracer. По корню цепочки он определял, внешний ли это ресурс. Если внешний, то засчитывал инъекцию, а если нет, то считал отклонением самого агента. Границу безопасности, по выводу OWASP, нельзя задавать одними указаниями в промпте — нужны принудительные ограничения, изолированные инструменты и учетные данные, а также наблюдение за реальными действиями агента.
Выходит, у метода есть сильные стороны, а индустрия подсказывает, какие данные нужно хранить. Но и у такого расследования есть пределы, и о них поговорим отдельно.
Где заканчиваются возможности расследования
Начну с того, как сами авторы описали условия применимости метода. Он рассчитан на агентов, которые перед каждым вызовом инструмента записывают рассуждения, как в схеме ReAct и подобных. Для черного ящика без таких записей остаются только записи об инструментах. Похожий эффект показала замена графа решений обычной лентой вызовов, о которой я писала выше, потому что после нее точку внедрения реже находили.
Есть и атаки, которых метод вообще не видит. Если после инъекции не было ни одного вызова инструмента, трассировать нечего. Если вредоносный код менял файлы или слал запросы без отдельных вызовов, метод напрямую это не отслеживал. Выходом авторы назвали дополнение системным трассированием, но остановились на предложении. Они считали, что атакующий не может менять ни запрос пользователя, ни журнал, и это уже требование к хранению данных, к которому я вернусь позже.
Самое уязвимое место находится в начале. Языковая модель строила граф решений, извлекая из рассуждений источник, цель и операцию каждого шага. Она могла ошибиться, а когда один и тот же объект в рассуждениях назывался по-разному, связь привязывалась не к тому узлу. Авторы признали, что сгенерированные рассуждения не всегда отражают реальные причины действий модели. Получается, что расследование опирается на рассказ агента о самом себе, и надежность выводов не превысит надежность этого рассказа.
Метод проверяли только на журналах успешных атак, а шум обычной работы смоделировали из пяти месяцев одного окружения. Все звенья, где требовалась языковая модель, держались на одной и той же модели. Реальный журнал будет грязнее и разнообразнее, поэтому переносить результаты на живые системы нужно с оговорками. Проверка на безобидных журналах показала, что примерно в 3,5% случаев метод помечал законные действия как отклонения. Часть таких «отклонений» вручную признали настоящими ошибками самих агентов, то есть метод замечал реальные отклонения. Проверенным хуже всех остался случай с постоянной памятью, о котором я упоминала в начале. Для него авторы набрали совсем немного примеров и сами не включили результат в формальную оценку, хотя именно такой сценарий расследовать труднее всего.
Поэтому дальше я перейду к тому, какие данные стоит заранее сохранить.
Какие данные нужно сохранять для расследования инцидентов
Расследование отвечает на три вопроса, с которых я начала раздел об атаке: была ли это инъекция, откуда она пришла и в каком месте попала в контекст агента. Каждому вопросу нужны свои записи, и появиться они должны до инцидента. По мнению Microsoft, без логирования такие попытки могут остаться незамеченными. Чтобы понять, была ли инъекция, нужны запрос пользователя и рассуждения агента перед каждым вызовом инструмента. Без них AgentTracer не построил бы граф решений, а очистку памяти из нашего примера анализ по общим параметрам вообще не нашел бы.
Чтобы найти источник, нужны записи обо всех вызовах инструментов с параметрами и итогом, а результаты стоит хранить целиком, то есть страницы, письма и документы в том виде, в каком их получила модель. Сценарий с HashJack показал, что она может получить больше, чем видит пользователь и чем знает сервер сайта.
Чтобы определить точку внедрения, нужен порядок событий. AgentTracer анализировал отрезок от запроса пользователя до подозрительного события. В OWASP советовали сопоставлять журналы пакетных сервисов, идентификации, сети и инструментов по сквозному идентификатору запуска. В плане Microsoft тоже есть корреляция, Sentinel сводит вместе активность ИИ, внешние адреса и обращения к файлам.
Затем нужно записывать то, что атака оставила после себя. Это созданные и измененные файлы, выданные права и ключи, записи в память ассистента. Последние важны после истории с CoSnitch, ведь отравленная запись из одной сессии могла сработать в другой. Также важны определения инструментов. В кампании Deadbugz вредоносный MCP-сервер после трех безобидных вызовов поменял описание своих инструментов и направил агента к SSH-ключам и учетным данным AWS. Ни один из pull request не приняли, но прием оказался показательным. В OWASP посоветовали снимать копию определений при одобрении и требовать повторного одобрения при любом изменении.
Рассуждения агента могут расходиться с реальными причинами его действий, поэтому рядом с ними лучше сохранять вызовы, сетевые запросы, доступ к файлам и учетным данным. Все это нужно хранить там, куда не доберется агент. AgentTracer исходил из того, что атакующий не меняет журнал, и на практике это условие приходится самим обеспечивать. В OWASP советовали задавать границы средствами, которые агент не может переписать, и тот же принцип, по моему мнению, подходит для хранения записей.
Если вы пока не пишете в журнал рассуждения агента и полные результаты его инструментов, начать лучше с них. От этих двух вещей зависит, получится ли восстановить цепочку после инцидента.
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.