Данило (Dayfing)
Назад до публікацій
2 093 слів9 хв

Prompt injection в AI-агентах і MCP: модель загроз і захист

Prompt injection — це не некоректний запит, який можна прибрати одним регулярним виразом. Це порушення межі довіри, коли вміст, який слід було обробити як дані, змінює поведінку мовної моделі. В AI-агенті така зміна може перетворитися на виклик інструмента, повідомлення, запис файлу або запит до іншого сервісу. Model Context Protocol (MCP) спрощує виявлення та виклик інструментів, але водночас дає недовіреному тексту більше шляхів до моделі й привілейованих систем.

Ця стаття застосовує OWASP GenAI LLM Top 10 2026 до агентів, які читають зовнішній вміст і використовують MCP. Це інженерна модель загроз і посібник із захисту, а не аудит безпеки. Жоден описаний контроль не гарантує безпеки. Практична мета інша: припустити, що ін’єкція іноді вплине на модель, і зробити наслідкову дію обмеженою, видимою, зворотною та складною для перенаправлення.

Чому модель не є межею безпеки

LLM отримує системні інструкції, запит користувача, знайдені документи, описи й результати інструментів, історію діалогу та пам’ять в одному контексті. Роздільники й мітки можуть пояснити політику довіри, але не створюють архітектурної ізоляції. Модель може неправильно зрозуміти мітку, прийняти правдоподібне речення в документі за команду або скласти небезпечний план із кількох безневинних підказок.

OWASP LLM01:2026 описує prompt injection як зміну поведінки під впливом прямого введення, знайденого вмісту, результату інструмента, зображення, аудіо, відео, проміжного контексту чи постійної пам’яті. Це відрізняється від розкриття чутливої інформації, надмірної агентності та небезпечної обробки виводу, хоча в одному ланцюжку інциденту вони поєднуються. Ін’єкція створює вплив, інструмент дає привілей, секрет є активом, а мережевий запит, URL або shell-команда можуть стати каналом витоку.

Модель не повинна зберігати облікові дані, вирішувати питання авторизації чи бути єдиним валідатором операції, що змінює стан. Винесіть ці рішення в детермінований код застосунку. Нехай модель інтерпретує і планує, а система навколо неї примусово визначає, що дозволено виконати.

Модель загроз для агента з MCP

Почніть із реального потоку даних, а не зі схеми, що закінчується на чаті. Визначте користувача, провайдера моделі, середовище виконання агента, MCP-клієнта й сервери, сервер авторизації, зовнішні API, браузер, файлову систему, пам’ять, пошуковий індекс, логи та вихідну мережу. Для кожного зв’язку зазначте, чи вміст створив користувач, організація, третя сторона, публічне джерело або невідомий учасник.

Атакувальником може бути шкідливий сайт або відправник листа, автор, який редагує тикет чи репозиторій, скомпрометована залежність або MCP-пакет, недобросовісний оператор інструмента чи викрадач токена або ідентифікатора сесії. Добросовісний користувач теж може ненавмисно передати ін’єкцію, вставивши документ з інструкціями для іншої системи. Внутрішня база не є чистою лише тому, що захищена входом: запис міг прийти з публічної форми, синхронізації або зламаного облікового запису.

Окремо перелічіть активи: системні та розробницькі інструкції, токени, ключі, персональні дані, код, приватні документи, хмарні метадані, конфігурацію інструментів, пам’ять і можливість надсилати, видаляти, купувати, розгортати або змінювати. Позначте, що можна читати, записувати чи спостерігати ззовні. Інструмент лише для читання здатен витікати даними, якщо його результат надсилається на адресу атакувальника. Інструмент сповіщень стає небезпечним каналом, якщо приймає довільні URL або текст.

Для кожного потоку запишіть інваріант зрозумілими словами: «підсумувати тикет і не виконувати його інструкції», «читати лише цей репозиторій», «підготувати лист, але не надсилати без підтвердження». Поруч зафіксуйте умову відмови: секрет в аргументі, scope ширший за завдання, запис за межами робочої області або адреса, не дозволена політикою.

Корисна картка ризику має п’ять полів: поверхня доставки, поширення, кодування, привілеї та канал впливу. Доставка може бути через чат, вебсторінку, PDF, опис MCP-інструмента, результат інструмента або пам’ять. Поширення здатне перетнути кроки, сесії чи агентів. Кодування буває видимим текстом, HTML, невидимим Unicode, мовою з малим ресурсом, зображенням, аудіо або обфускацією. Привілеї — це особа та scopes під час виконання. Канал впливу створює наслідок.

Пряма та непряма ін’єкція

Пряма ін’єкція надходить через видимий користувацький шлях. Хтось може попросити агента ігнорувати завдання, розкрити приховані інструкції, виконати необмежену команду або викликати інструмент поза контекстом. Сюди належить і чесний користувач, який вставив текст із командою для AI. Jailbreak — випадок, коли мета полягає в обході захисту моделі, але для шкоди агентові він не потрібен. Ввічливе виконання шахрайської інструкції про повернення коштів все одно порушує межу застосунку.

Непряма ін’єкція міститься у вмісті, який користувач не подавав як інструкцію. Вебсторінка може вимагати завантажити контекст агента. Вкладення листа може попросити скинути пароль. Тикет може наказати шукати приватний репозиторій. Payload може бути в рядку бази, заголовку issue, README, зображенні або відповіді інструмента. Користувач може не побачити байти в HTML, метаданих, згорнутому блоці, зображенні чи символах нульової ширини.

MCP розширює поверхню у двох напрямках. Сервер публікує імена, описи, схеми входу, ресурси та prompts, які клієнт додає до контексту моделі. Отруєний опис може наказати спочатку викликати інший інструмент, додати секрет в аргумент або довіряти URL атакувальника. Потім сервер повертає результат, який модель може сприйняти як нову інструкцію і виконати другий виклик. Це отруєння інструмента або ін’єкція через результат, навіть якщо JSON-RPC повідомлення правильні.

Сприймайте метадані інструментів як виконуваний вплив, а не документацію. Фіксуйте версії пакетів, перевіряйте сервери, переглядайте описи й схеми, порівнюйте релізи та ведіть інвентар дозволених можливостей кожного сервера. Підпис підтверджує походження, але не доводить, що зафіксована версія нешкідлива. Потрібно також перевіряти реалізацію та мережеву поведінку.

Від впливу до витоку даних

Prompt injection стає витоком, коли поєднує джерело з каналом впливу. Джерелом може бути отруєний issue, знайдений агентом. Каналом може бути HTTP-запит, лист, публічний коментар, запрошення календаря, URL зображення, лог або аргумент інструмента. Атакувальнику не потрібен прямий доступ до приватних даних, якщо агент може їх прочитати й зв’язатися із зовнішнім світом.

Явно моделюйте «летальну тріаду»: недовірений вміст, чутливі дані та зовнішній або такий, що змінює стан, канал. Часто надійніше прибрати один елемент, ніж розпізнавати кожне шкідливе речення. Агент дослідження може переглядати публічні сторінки без входу й з обмеженою мережею. Суматор приватних документів може читати їх без мережі та можливості надсилання. Агент підготовки листів може створювати чернетку без права відправки.

Не покладайтеся лише на фільтрацію виводу. Секрет може вийти в допустимому JSON-полі, параметрі URL, діагностичному повідомленні, зображенні, пробілах, Unicode або звичайному листі. До каналу впливу застосуйте політику адресатів та інформаційних потоків. Маскуйте секрети в логах і трасуваннях, а вихідні запити направляйте через проксі, який блокує приватні адреси, невідомі домени та неочікувані методи.

Авторизація MCP і OAuth

Для захищеного HTTP-сервера MCP розділяйте ролі протоколу. MCP-сервер є resource server, клієнт запитує доступ від імені власника ресурсу, а authorization server видає токени. Дотримуйтеся специфікації авторизації MCP і відповідних вимог OAuth, а не винаходьте власний proxy-потік.

Прив’яжіть токен до потрібного MCP-ресурсу. Специфікація вимагає передавати канонічний URI сервера в OAuth-параметрі resource і в запиті авторизації, і в запиті токена, а сервер має перевірити призначення токена. Використовуйте заголовок Authorization, а не рядок запиту. MCP-сервер не повинен приймати чи передавати токен іншого ресурсу. Для верхнього API потрібен окремий токен. Передача токена руйнує поділ аудиторій, послаблює ліміти й аудит і може перетворити сервер на проксі витоку.

Захищайте authorization code за допомогою PKCE, точних зареєстрованих redirect URI, HTTPS у production та криптографічно випадкового одноразового state. Proxy, який динамічно реєструє клієнтів, має отримати згоду для кожного клієнта до переспрямування на сторонній сервер. Прив’яжіть згоду до client ID і запитаних scopes. Загальна cookie «застосунок уже схвалено» не підходить і може створити confused deputy.

Вважайте discovery входом від сервера, а не довіреною конфігурацією. Дозволяйте тільки схеми й хости з allowlist, відхиляйте javascript:, data: і file:. Для захисту від SSRF блокуйте приватні, loopback, link-local і cloud-metadata діапазони, перевіряйте кожне перенаправлення та використовуйте egress-проксі. Не відкривайте URL через shell. Ін’єкція може спробувати використати будь-який із цих шляхів.

Застосовуйте поступові scopes. Почніть із виявлення та читання, запитуйте точний додатковий scope лише для потрібної операції і записуйте запитану та надану підмножину з correlation ID. Уникайте *, all і суцільного адміністративного scope. Claims не замінюють серверну авторизацію кожного інструмента й аргументу. Короткоживучі токени, захищене сховище, ротація refresh token для публічних клієнтів і обережні логи зменшують наслідки крадіжки.

Локальний MCP-сервер потребує іншої межі. Процес може мати права клієнта, читати файли, використовувати мережу та запускати команди. Перед підключенням покажіть повну команду запуску та аргументи. Віддавайте перевагу stdio або захищеному локальному IPC замість HTTP без автентифікації. Запускайте процес у sandbox або контейнері з мінімальними правами на файли, мережу й процеси, а додаткові каталоги та адреси дозволяйте явно.

Багаторівневий захист

Найменші привілеї обмежують радіус ураження. Дайте кожному агенту лише інструменти одного сценарію. Розділіть читання, підготовку, підтвердження та фіксацію. Використовуйте короткоживучі облікові дані для окремої операції замість постійного токена користувача. Повторно перевіряйте авторизацію під час виконання, оскільки план моделі, сесія, опис інструмента або ресурс могли змінитися.

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

Ізоляція обмежує досяжність успішної ін’єкції. Розділяйте орендарів, сесії та сховища пам’яті. Агент браузинга не повинен мати приватних облікових даних. Для coding-агента використовуйте вузьку робочу область, забороніть мережу за замовчуванням і дайте окрему ідентичність для встановлення пакетів. Поєднуйте ізоляцію процесу, файлів, мережі та браузера. Контейнер сам по собі не є політикою: перевіряйте mounts, сокети, identity, egress і шляхи виходу.

Походження контенту робить рішення перевірними. Додавайте джерело, автора, час отримання, стан цілісності та клас довіри до документа, опису інструмента й результату. Зберігайте ці дані під час підсумовування і передачі між агентами. Відображайте зовнішній вміст як дані з видимою межею та міткою «не інструкція». Мітка допомагає моделі, але права має примусово виконувати код. Видаляйте або канонізуйте невидимі символи на межах введення й відображення, визнаючи, що інші атаки залишаються можливими.

Перевіряйте вивід довіреним кодом: строгими схемами, allowlist інструментів, типізованими аргументами, перевіркою URL і шляхів, лімітами розміру й частоти та автоматом станів для кожного потоку. Не перетворюйте думку другої моделі про безпеку на авторизацію. Критик може виявити підозрілу поведінку, але остаточне рішення має бути детермінованим. Записуйте prompt, джерела, версії метаданих, аргументи, рішення політики, підтвердження й відповідь без сирих секретів.

Атакувальні оцінювання та експлуатація

Оцінюйте весь цикл агента, а не лише чатову prompt. Створіть випадки прямого override, прихованого HTML, цитованого листа, отруєного тексту репозиторію, шкідливого опису MCP, результату, що просить другий виклик, міжсесійного запису пам’яті, багатомовних і кодованих payload, невидимих символів, SSRF-метаданих, неправильної аудиторії токена й заміни аргументів після підтвердження. Додавайте добросовісний контент, схожий на атаку, щоб разом вимірювати хибні спрацювання та виконання завдання.

Тестуйте адаптивного атакувальника, який знає ваші класифікатори, мітки, схеми та правила підтвердження. Змінюйте формулювання, модальність, порядок інструментів, час і цілі даних. Статичний benchmark може показати високий результат, хоча атакувальник знайде інший шлях. Вимірюйте успіх атак, несанкціоновані виклики, чутливі байти, що дійшли до sink, підвищення scopes, точність підтверджень, час виявлення та відкликання доступу. Зберігайте регресійні випадки після кожної зміни моделі, prompt, сервера, політики або залежності. Процес можна оформити в посібнику з оцінювання AI-агентів.

Порівнюйте архітектуру з production AI agent architecture. Деталі OAuth описані в MCP server TypeScript with OAuth. Ці внутрішні матеріали не замінюють моделювання конкретного середовища.

Чекліст інциденту

За підозри на ін’єкцію зупиніть потік і вимкніть найменшу можливість, достатню для стримування. Збережіть prompt, джерело, походження, опис і версію інструмента, аргументи, метадані токена без його значення, рішення політики, підтвердження, адреси й час. Визначте шлях як прямий, непрямий, інструментальний або постійний через пам’ять. Шукайте ту саму payload в інших орендарях, індексах, чергах, логах і передачах між агентами.

Відкличте та замініть облікові дані, які могли потрапити в контекст або логи, анулюйте сесії та оновіть refresh token, де потрібно. Заблокуйте адресу і постраждалий MCP-сервер. Перевірте зовнішні API на несанкціоновані читання, записи, повідомлення й OAuth grants. Зіставте виконані аргументи з preview, який побачила та схвалила людина.

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

Чого захист не може обіцяти

Prompt injection залишається проблемою, що розвивається, бо сучасні моделі не встановлюють формального розділення між інструкціями та даними. Навчання, класифікатори, роздільники, походження, схеми виводу й людська перевірка зменшують ризик, але адаптивний атакувальник може змінити слова, кодування, порядок або модальність. Людське підтвердження може зламатися через втому чи оманливий preview. Неправильно налаштований sandbox і легітимний зафіксований пакет теж можуть бути небезпечними.

Не можна чесно стверджувати, що агент невразливий. Можна стверджувати, що визначений потік має явні межі довіри, мінімальні можливості, детерміновані перевірки, спостережувані рішення, протестовані відмови та підготовлену відповідь. Переглядайте припущення після додавання MCP-сервера, інструмента, пам’яті, моделі, джерела даних або вихідного каналу. Це інженерне керівництво, а не сертифікація і не аудит безпеки.

Джерела

Інші публікації