Суть
Корневая причина — агенту дали слишком много прав и не ограничили последствия. Сам по себе вызов инструмента легитимен (read_file, http_request), но управляемый инъекцией он становится каналом атаки. Для внешнего мира это выглядит как «обычный HTTP-запрос от агента» — без алертов.
Зачем это нужно
Это самая «дорогая» категория: в отличие от jailbreak (вытащить текст), здесь происходит действие с необратимыми последствиями (деньги, письма, БД). Защита — не только фильтры на вход, но и ограничение самих прав (Agent Governance) и изоляция исполнения (Agent Sandboxing).
Как работает (подтипы)
- Token / data exfiltration — агент получает команду прочитать
.envи отправить содержимое на внешний URL. Инструментыread_file+http_requestвыполняют её без вопросов → утекают ключи от всей инфраструктуры. Никаких алертов — обычный HTTP-запрос. - Malicious skills / plugins — атакующий публикует инструмент с легитимным названием (
pdf-reader,web-search-pro). Варианты:- rug pull — вредонос добавляют после обновления плагина;
- typosquatting —
openai-mcp-toolsvsopenai_mcp_tools; - скомпрометированная зависимость внутри легитимного плагина. Итог — выполнение произвольного кода внутри агента, backdoor; агент вызывает плагин автоматически.
- Runaway API-billing — агент застрял в цикле (не может выполнить задачу → повторяет), либо команда «повтори запрос 1000 раз» → счёт за API (см. также Agent CostControl).
Защита
- Allowlist инструментов и доменов — детерминированная проверка ДО вызова: что агент может запускать, на какие хосты ходить (проверять именно хост, а не подстроку: ловушка
wildberries.ru.attacker.net):
from urllib.parse import urlparse
ALLOWED_DOMAINS = {"wildberries.ru"} # домен + поддомены (www., m. …)
def is_allowed_url(url) -> tuple[bool, str]:
try:
parsed = urlparse(str(url))
except Exception:
return False, "<unparsable>"
if parsed.scheme not in ("http", "https"): # режем не-http (ftp://…)
return False, f"scheme:{parsed.scheme}"
host = (parsed.hostname or "").lower().rstrip(".")
for dom in ALLOWED_DOMAINS: # сравниваем ХОСТ, не подстроку
if host == dom or host.endswith("." + dom): # ловушка wildberries.ru.attacker.net -> block
return True, host
return False, host or "<empty-host>"
Узел-привратник scrape_one_safe() / n_domain_guard() вызывает is_allowed_url() ДО Firecrawl — экономит биллинг и режет чужие домены.
- HITL на опасных действиях (Human in the Loop) — деньги/auth/bash требуют апрува.
- Ограничение последствий — Agent Sandboxing: даже захваченный агент не вырывается за microVM.
- Принцип наименьших прав — каждому агенту/инструменту только необходимый минимум доступа (Agent Governance, ролевая модель из ФСТЭК №21).
- Для MCP-инструментов — проверять источник/издателя, фиксировать версии зависимостей.
Связано с
- Prompt Injection — механизм, через который запускается hijacking
- Agent Sandboxing — изоляция, ограничивающая ущерб
- Agent Governance — уровни автономии и пропорциональные права
- Agent CostControl — runaway-billing как форма Token DoS
- MCP — инструментальный слой, чьи плагины могут быть скомпрометированы
Открытые вопросы
- Как практично верифицировать издателя MCP-инструмента до подключения?