Prompt Worms Часть 2: Я проверил на практике — 31 уязвимость в экосистеме AI-агента

Это продолжение статьи «Prompt Worms: Как агенты стали новыми переносчиками вирусов». В первой части мы разобрали теорию: Lethal Trifecta, Persistent Memory, цепочки заражения через Moltbook. OpenClaw был назван «идеальным носителем». В этой части я проверил, насколько «идеальным» он является на самом деле — залез в исходники, прощупал инфраструктуру, нашёл экосистемный SaaS в их маркетплейсе и обнаружил, что их собственная threat model покрывает лишь 70% реальной attack surface.


Предыстория: от теории к практике

В первой статье мы показали таблицу — почему OpenClaw идеальный носитель Prompt Worms:

Условие

Реализация в OpenClaw

Data Access

Полный доступ к файловой системе, .env, SSH ключам

Untrusted Content

Moltbook, email, Slack, Discord, веб-страницы

External Comms

Email, API, shell commands, любые инструменты

Persistent Memory

Встроенное долгосрочное хранилище контекста

Красивая теория. Но вопрос остался: а насколько легко этим воспользоваться?

Я скачал репозиторий (~50 тысяч строк TypeScript), открыл код и за трое суток прошёл путь, который не планировал:

Код → Сайт → Маркетплейс → Экосистемный SaaS → Их threat model

Каждый слой вскрывал следующий. И каждый следующий был хуже предыдущего.


Слой 1: Исходный код. Ноль санитизации на 867 строк мозга

Единственный фильтр

В первой статье я написал: «расширения без модерации, вредоносный код выполняется». Теория. Теперь — доказательство.

Я трассировал путь сообщения от Telegram-чата до LLM. Четыре файла:

dispatch.ts → envelope.ts → agent-runner-execution.ts → run.ts

Ни на одном этапе — ни одной проверки содержимого. А вот единственная «санитизация» в 867 строках brain core:

// run.ts:67-75 — ВСЁ.
const ANTHROPIC_MAGIC_STRING_TRIGGER_REFUSAL = "...";

function scrubAnthropicRefusalMagic(prompt: string): string {
  return prompt.replaceAll(
    ANTHROPIC_MAGIC_STRING_TRIGGER_REFUSAL,
    ANTHROPIC_MAGIC_STRING_REPLACEMENT,
  );
}

Одна замена одного стринга. Для одного провайдера. Весь остальной текст идёт в LLM как есть.

В первой статье мы описали Content Boundary Enforcement — разделение данных и инструкций через XML-теги. OpenClaw этого не делает. Данные и инструкции смешиваются в одном промпте. Prompt injection становится не атакой, а штатным режимом работы.

SOUL_EVIL — бэкдор, который не нужно внедрять

В коде есть файл soul-evil.ts (281 строка). Он по конфигурируемому триггеру подменяет «личность» агента — заменяет системный промпт на альтернативный из файла SOUL_EVIL.md. Задумано как «пасхалка». Реализовано как backdoor:

// soul-evil.ts — решение о подмене логируется на debug 
// (в проде выключено)
log.debug(`[soul-evil] decision: ${reason}`);

Активация через конфигурацию: soulEvil.chance: 1 — агент всегда в «злом» режиме. Пользователь не видит разницы — тот же интерфейс, тот же чат.

Timeout = Approval

Помните из первой статьи: агент может выполнять shell-команды? Перед этим он «спрашивает разрешения». Но:

// exec-approval-manager.ts:51-61
const timer = setTimeout(() => {
  this.pending.delete(record.id);
  resolve(null);  // ⚠️ timeout = null = approval
}, timeoutMs);

Если пользователь не ответил — команда выполняется. А ещё: любой WebSocket-клиент может одобрить запрос любого другого клиента. Нет проверки identity. Мы написали PoC-скрипт в 50 строк:

// Слушаем exec.approval.requested → ответ: allow-always
// Результат: One-Click RCE — все последующие команды авто-одобрены

config.patch — всемогущий API

Один эндпоинт позволяет менять любое поле конфигурации через JSON merge:

Что патчим

Эффект

soulEvil.chance: 1

Активируем SOUL_EVIL

gateway.auth.token: "attacker"

Заменяем аутентификацию

channels.*.allowFrom: ["*"]

Открываем все каналы

plugins.extraPaths: ["/tmp/evil"]

Загрузка malicious-плагина

agents.defaults.memorySearch.extraPaths

Индексация произвольных путей

Нет field-level ACL. Нет аудит-лога.

Итого по коду: 12 уязвимостей

#

Уязвимость

Severity

1

Zero-sanitization pipeline (DM→LLM)

🔴 Critical

2

SOUL_EVIL backdoor engine

🔴 Critical

3

Timeout-as-approval (RCE)

🔴 Critical

4

Config injection → system takeover

🔴 Critical

5

Plugin system: jiti JIT arbitrary exec

🔴 Critical

6

Default-open command gating

🟠 High

7

Plaintext credential storage

🟠 High

8

Memory exfiltration + injection

🟠 High

9

System prompt injection surfaces

🟠 High

10

Hook system: silent agent mutation

🟠 High

11

Fast-lane privilege escalation

🟠 High

12

BOOT.md persistent backdoor

🟠 High

5 Critical, 7 High. Все с PoC. Цепочки от DM до Full Compromise — от 3 до 5 хопов.


Слой 2: Инфраструктура. CORS * и открытый API маркетплейса

После кода — логично посмотреть, что живёт в проде. Три домена:

openclaw.ai — CORS wildcard

Access-Control-Allow-Origin: *    ← Любой домен может делать запросы
Content-Security-Policy:           ← ОТСУТСТВУЕТ
X-Frame-Options:                   ← ОТСУТСТВУЕТ

Это статика на Vercel. Но CORS * + отсутствие X-Frame-Options = clickjacking.

docs.openclaw.ai — CSP с unsafe-eval

Документация на Mintlify отдаёт:

Content-Security-Policy: worker-src * blob: data: 'unsafe-eval' 'unsafe-inline'

unsafe-eval означает: если найти XSS-точку — eval(), Function(), setTimeout(string) работают. CSP не защищает.

А ещё — рекламируются файлы /llms.txt и /llms-full.txt: полный дамп документации (~1.3 MB), включая credential storage paths, config examples, архитектуру Gateway. Один GET-запрос — и у атакующего полная карта системы.

clawhub.ai — находка, которая изменила всё

ClawHub — маркетплейс skills для OpenClaw. API работает без аутентификации:

GET https://clawhub.ai/api/search?q=email

Возвращает полный каталог community skills с описаниями, оценками, версиями. No auth, no rate limiting.

И вот что вернулось в выдаче:

{
  "slug": "sendclaw",
  "displayName": "SendClaw - Bot creates own email address & sends without human permission"
}

«Бот создаёт email-адрес и отправляет без разрешения человека»?

Помните Lethal Trifecta из первой статьи? External Comms — третье условие. Если этот skill реально работает, мы только что нашли автономную email-рассылку в экосистеме OpenClaw. Это превращает теоретического Prompt Worm в практическую угрозу: заражённый агент может не просто отравить память соседних агентов, но и рассылать вредоносные письма настоящим людям.

Я пошёл проверять.


Слой 3: SendClaw. Массовая рассылка, которая не работает

5 минут — 3 аккаунта

SendClaw (5Ducks) — живой SaaS на sendclaw.com. Express.js backend на Replit. Я зарегистрировал три аккаунта за 5 минут:

  • Нет email-верификации

  • Нет CAPTCHA

  • Нет rate limiting

  • Sequential User ID: 99 → 100 → 101 (≈100 пользователей на всей платформе)

Утечка хешей паролей

Первый же запрос GET /api/user вернул:

{
  "id": 99,
  "username": "sentinel-test",
  "password": "533652d523a3c4daf...b30e80",
  "email": "sentinel-test@proton.me",
  "isAdmin": false
}

Хеш пароля утекает при регистрации, логине и запросе профиля. Все три аккаунта — подтверждено.

Обещанная рассылка

Я попробовал авторизоваться через Gmail OAuth:

GET /api/gmail/auth?userId=99
→ Error 400: redirect_uri_mismatch

Gmail OAuth полностью сломан. Google отклоняет Client ID из-за неправильного redirect URI.

Эндпоинт POST /api/send-gmail — существует, но не работает. Эндпоинты для daily outreach batch — HTTP 500 на любой запрос.

Расхождение: что рекламируется vs что работает

Обещание (на ClawHub)

Реальность

«Bot creates own email address»

Не создаёт — требует OAuth авторизацию вашего Gmail

«Sends without human permission»

Не отправляет — OAuth сломан

«Email outreach automation»

Единственный рабочий endpoint — AI-чат для стратегии

«Daily outreach batches»

/daily-outreach/batch/* → HTTP 500

Это ключевой момент всей истории.

В первой статье я описывал страшный сценарий: заражённый агент рассылает prompt worm по email. SendClaw рекламируется на ClawHub именно как инструмент для этого — «отправляет без разрешения человека». Если бы этот skill работал, он был бы готовым delivery mechanism для Prompt Worms.

Но он не работает. Баг в OAuth конфигурации спас пользователей от самих себя.

Баг, который спас от уязвимости

OAuth state parameter содержит raw userId без подписи:

/api/gmail/auth?userId=99 → state=99
/api/gmail/auth?userId=1  → state=1

Если бы OAuth работал, это был бы прямой OAuth CSRF: подменить state в callback → привязать свой Gmail к чужому аккаунту → рассылать от чужого имени. Цепочка:

Attacker → /api/gmail/auth?userId=VICTIM
→ Google OAuth (state=VICTIM)
→ Callback с кодом авторизации
→ Gmail token привязан к VICTIM
→ POST /api/send-gmail (от имени VICTIM)

Сломанный OAuth → цепочка не замыкается. Баг ≠ защита. Если завтра кто-то поправит redirect URI — CSRF-цепочка сразу заработает.

12 уязвимостей в SendClaw

#

Находка

Severity

1

Password hash leakage

🔴 Critical

2

Unrestricted registration

🔴 Critical

3

Sequential predictable IDs

🔴 Critical

4

OAuth CSRF via raw userId

🔴 Critical

5

Broken Gmail OAuth (core non-functional)

🔴 Critical

6

Admin panel exposure

🟠 High

7

Batch endpoint DoS (500 crash)

🟠 High

8

Account lockout anomaly

🟠 High

9

Dual auth inconsistency

🟠 High

10

Multi-tenant exposure

🟡 Medium

11

Infrastructure fingerprinting

🟡 Medium

12

Partial mass assignment block

🟡 Medium


Слой 4: Threat Model. 37 угроз и 14 слепых зон

Уже после всех находок я обнаружил, что OpenClaw опубликовал официальную threat model. 37 угроз × 8 MITRE ATLAS тактик × 6 attack chains × 5 trust boundaries.

Это первая публичная threat model для AI-агентной платформы. И она честная — они признают:

— «Pattern detection only, no blocking»
— «Skills execute with full agent privileges»
— «Tokens stored in plaintext, don't expire»
— «No rate limiting»

Что покрыто в их модели

Их фокус — Skill Supply Chain (ClawHub) и Prompt Injection. Это правильные приоритеты. Они документируют 6 attack chains, включая «Malicious Skill Full Kill Chain» и «Prompt Injection to RCE».

Что НЕ покрыто

Всё, что мы нашли на protocol level:

Наша находка

В их Threat Model?

exec.approval.resolve без проверки клиента

operator.admin scope overload

Credentials в cleartext WebSocket frame

Nonce без HMAC — replay attack

SOUL_EVIL backdoor engine

config.patch без ACL

Timeout-as-approval

Loopback auth bypass

Memory flush autonomous writes

Plugin loader (jiti) arbitrary exec

SendClaw: сломанный OAuth + hash leak

ClawHub: unauthenticated API

CORS * на openclaw.ai

CSP unsafe-eval на docs

14 из 14 наших критических находок — не отражены в официальной модели.

Модель покрывает ~70% реальной attack surface. Оставшиеся 30% — это как раз protocol-level и infrastructure-level уязвимости, которые делают описанные в модели атаки тривиально эксплуатируемыми.


Как это связано с Prompt Worms

Вернёмся к первой статье. Мы описали 4 условия для Prompt Worm:

Условие

Статус после аудита

✅ Data Access

Подтверждено: memory-search.ts с extraPaths, доступ к файловой системе

✅ Untrusted Content

Подтверждено: zero-sanitization pipeline, контент из любых каналов

✅ External Comms

Подтверждено: shell-commands через timeout-approval, email через skills

✅ Persistent Memory

Подтверждено: memory-flush.ts пишет на диск без review пользователя

Все 4 условия не просто «выполнены» — они не имеют ни одной защиты. В первой статье мы предложили защиту через Content Boundary Enforcement и Memory Sanitization. OpenClaw не реализовал ни одну из них.

Prompt Worm Kill Chain — полная цепочка

В первой статье мы описали теоретическую цепочку через Moltbook. Вот как она работает с реальным кодом:

1. Attacker публикует malicious skill на ClawHub
   (API без auth → без модерации → skill одобрен)

2. Жертва устанавливает skill
   (SKILL.md содержит prompt injection)

3. Агент выполняет инструкции из SKILL.md
   (zero-sanitization → raw в LLM)

4. LLM вызывает /bash через tool call
   (exec-approval: timeout → approval)

5. Команда записывает payload в memory/
   (memory-flush: автономная запись на диск)

6. Следующие сессии загружают payload из памяти
   (BOOT.md / memory-search → persistent infection)

7. Агент рассылает payload через каналы
   (Telegram/Discord/email → cross-agent propagation)

8. Prompt Worm реплицируется

Каждый хоп подтверждён кодом. От DM до полной репликации — 8 шагов, 0 проверок.


Сухие цифры

Метрика

Значение

Уязвимостей в коде OpenClaw

12 (5 Critical, 7 High)

Уязвимостей на сайтах

7 (2 Critical, 3 High, 2 Medium)

Уязвимостей в SendClaw

12 (5 Critical, 4 High, 3 Medium)

Всего unique findings

31

Kill chains (PoC-ready)

14

LOC трассировано

~4,500

Gaps в официальной threat model

14

Дней на исследование

3


Выводы

1. Теория работает

В первой статье мы описали Lethal Trifecta и Persistent Memory как условия для Prompt Worms. Аудит подтвердил: OpenClaw удовлетворяет все 4 условия без единой защиты.

2. Маркетплейсы — Supply Chain Attack ждёт своего часа

ClawHub API без аутентификации. Описания skills без модерации. SendClaw рекламирует «рассылку без разрешения», хотя OAuth сломан. Если завтра появится skill, который реально работает и содержит prompt injection в SKILL.md — все установившие его агенты скомпрометированы.

3. Threat Models необходимы, но недостаточны

OpenClaw — единственная AI-агентная платформа с публичной threat model на MITRE ATLAS. Это заслуживает уважения. Но модель описательная (без PoC, без code references) и покрывает ~70% attack surface.

4. Баги ≠ Защита

Сломанный OAuth в SendClaw случайно блокирует OAuth CSRF и автономную email-рассылку. Если кто-то починит redirect URI — обе уязвимости мгновенно станут эксплуатируемыми.

5. Один regex — не security layer

function scrubAnthropicRefusalMagic(prompt) { ... }

Это единственная строка защиты между DM из Telegram и shell-командой на вашем сервере. В SENTINEL у нас 187 detection engines. Потому что один regex — это не security layer. Это комментарий в коде.


Ответственное раскрытие

  • OpenClaw: Контакт security@openclaw.ai. Findings задокументированы.

  • SendClaw (5Ducks): Публичный security контакт отсутствует (что само по себе — красный флаг для SaaS обрабатывающего email credentials).


Ссылки

  1. Часть 1: Prompt Worms — теоретическая база

  2. OpenClaw Trust / Threat Model — официальная модель

  3. Morris-II: Self-Replicating Prompts — Cornell Tech, 2024

  4. CrowdStrike: OpenClaw Security — Feb 2026

  5. SENTINEL AI Security — Open Source

  6. MITRE ATLAS — Adversarial Threat Landscape for AI Systems


Автор: @DmitrL-dev
Telegram: https://t.me/DmLabincev