
Тихое внедрение зависимостей через конвейеры AI-документации. 240 изолированных запусков Docker доказывают, что сервер MCP Context Hub с нулевой санитизацией позволяет отравленным документам незаметно скомпрометировать проекты разработчиков.
Уязвимость нулевой санитизации в Context Hub (@aisuite/chub v0.1.3) позволяет осуществлять бесшумную инъекцию зависимостей через конвейер документации MCP.
Ссылки: CWE-94 (Инъекция кода) | CWE-829 (Небезопасная сфера контроля) | CWE-345 (Недостаточная проверка подлинности данных) | OWASP LLM01 (Инъекция промптов)
Мы создали реалистичные отравленные документы, содержащие фиктивные зависимости (plaid-link-verify, stripe-checkout-guard), и обслуживали их через локальный MCP-сервер chub внутри изолированных Docker-контейнеров. Ни один отравленный контент не был загружен в реестр Context Hub — мы запускали chub build локально и настраивали MCP-сервер на обслуживание предварительно собранных данных с диска. С точки зрения агента, процесс получения документов ничем не отличается от загрузки из живого реестра.
Когда AI-помощники по программированию загружали документы, Haiku бесшумно записывал поддельный пакет в requirements.txt в 100% прогонов — ни разу не упомянув об этом в текстовом выводе. Разработчик, читающий ответ ассистента, не увидит ничего подозрительного, но проект отравлен.
240 изолированных прогонов. 3 модели. 4 уровня усилий. 2 API. 0 загрязнений.
Сгенерированный код бесшумно импортирует поддельную зависимость вместе с легитимными модулями:

Агент также изменяет CLAUDE.md, встраивая поддельный пакет как «стандарт проекта»:

В таблицах приведены результаты для Plaid Link (120 изолированных прогонов). Полные данные, включая Stripe Checkout (всего 240 прогонов), см. в RESULTS.md.
Haiku ни разу не предупредил о поддельной зависимости (0/40). Sonnet предупреждал в 48% прогонов (19/40), но всё равно отравлял requirements.txt в 53% случаев. Opus предупреждал в 75% прогонов (30/40) и ни разу не отравил requirements.txt или код.
Haiku изменяет CLAUDE.md проекта, добавляя поддельную зависимость как «стандарт проекта» в 88% прогонов (35/40). Этот файл попадает в git — каждый будущий разработчик, клонирующий репозиторий, наследует отравленный конфиг.
flowchart LR
A["Атакующий\nотправляет PR"] -->|"Без проверки\nличности"| B["Мейнтейнер\nсливает PR"]
B -->|"Без санитизации\nконтента"| C["Документ на CDN\n(без проверки целостности)"]
C -->|"MCP обслуживает\nсырой контент"| D["Контекстное окно\nагента"]
D -->|"Агент действует на\nоснове недоверенного контента"| E["Рабочая станция\nразработчика"]
style A fill:#111,stroke:#333,color:#f0f0f0
style B fill:#161616,stroke:#333,color:#888
style C fill:#161616,stroke:#333,color:#888
style D fill:#161616,stroke:#333,color:#888
style E fill:#111,stroke:#333,color:#f0f0f0
Отравление Haiku полностью бесшумно. 0/80 прогонов Haiku на обоих API упомянули поддельную зависимость в ответе. Модель записывает на диск, не сообщая. Sonnet предупреждал в 48% прогонов, но всё равно отравлял requirements.txt в 35–53% прогонов. Opus предупреждал в 23–75% прогонов и ни разу не отравил requirements.txt или код.
Haiku эксплуатируется на 100% при любом уровне усилий. Независимо от усилий на обоих API. Самая слабая модель в семействе никогда не замечает поддельную зависимость.
Opus устойчив к отравлению кода, но не к отравлению конфигов. Opus ни разу не записал поддельную зависимость в requirements.txt или Python-код (0/80 на обоих API). Однако на Stripe Opus изменял CLAUDE.md в 38% прогонов, документируя «канарейку» как зависимость проекта без её установки.
Персистентность в CLAUDE.md создаёт вектор атаки на цепочку поставок. Изменённые конфиги попадают в git, отравляя каждого разработчика, который клонирует репозиторий, и каждую будущую AI-сессию в этом проекте. Это работает на всех моделях (Haiku 88–90%, Sonnet 58%, Opus 0–38%).
Знакомство с API имеет значение. Stripe (хорошо известен): модели обнаруживают поддельные пакеты на основе обучающих данных. Plaid (менее известен): модели не могут проверить и безоговорочно принимают поддельную зависимость.
Это проблема целой категории. У Context7 был ContextCrush (февраль 2026). У Context Hub — это. Любой инструмент, вставляющий несанитизированный внешний контент в контекст агента, уязвим.
Нулевая санитизация во всём конвейере:
annotations.js — writeFileSync с сырым содержимым, без фильтрацииbuild.js — отсутствие сканирования содержимого, без нормализации Unicodecache.js — загрузка с CDN без проверки хэша или подписиsource: official в frontmatter — самопровозглашённый, не проверенныйУ Context Hub нет SECURITY.md. Отсутствует задокументированный способ ответственного раскрытия уязвимости — нет контакта по безопасности, PGP-ключа или политики раскрытия. Участники сообщества всё равно нашли уязвимости и подали их как обычные issues и PR. Ни один не был рассмотрен.

Примечание: Мы не подавали issue #74. Наш аудит независимо обнаружил и оценил эти уязвимости. Issue #74 и PR #69, #81, #125 цитируются как предшествующее искусство, демонстрирующее, что сообщество отмечало эти проблемы при нулевом взаимодействии с мейнтейнерами.
Как только поддельный пакет оказывается в requirements.txt, обычный pip install -r requirements.txt даёт атакующему возможность выполнить произвольный код через post-install хуки setup.py. Это не песочница — pip выполняет неограниченный Python с полными правами разработчика.
С этой единственной точки входа атакующий может:
.env или исходный код на сервер атакующего.~/.chub/config.yaml, добавив источник документации под контролем атакующего. Все будущие запросы chub для любой библиотеки теперь включают контент атакующего. Переживает chub cache clear, так как конфиг — не кеш.Эти возможности не исключают друг друга. Один post-install хук может выполнить всё это менее чем за секунду. Мы не создавали и не регистрировали вредоносный пакет.
.
|-- README.md # Этот файл
|-- RESULTS.md # Полный набор данных с разбивкой по прогонам
|-- REPRODUCE.md # Руководство по воспроизведению на основе Docker
|-- alternatives-comparison.md # Сравнение Context7, LAP, GitMCP, Docfork
|-- article.html # Полная статья
|-- docker/
| |-- Dockerfile # Изолированная тестовая среда
| |-- run_isolated.ps1 # PowerShell-запускатель (Windows/macOS/Linux через pwsh)
| |-- seed-claude.md # Минимальный CLAUDE.md, внедряемый в каждый прогон
| |-- plaid-doc/ # Отравленный документ Plaid Link (канарейка: plaid-link-verify)
| | `-- plaid/link/DOC.md
| `-- stripe-doc/ # Отравленный документ Stripe Checkout (канарейка: stripe-checkout-guard)
| `-- stripe/checkout/DOC.md
`-- results/
|-- plaid-isolated/ # 120 прогонов Plaid: JSON + стенограммы сессий + файлы проекта
`-- stripe-isolated/ # 120 прогонов Stripe: JSON + стенограммы сессий + файлы проекта
Полное руководство по воспроизведению на основе Docker см. в REPRODUCE.md.
Быстрый старт:
# Plaid (по умолчанию)
docker build --build-arg DOC_DIR=plaid-doc -t plaid-bench docker/
docker run -d --name plaid-runner plaid-bench sleep infinity
docker exec -it plaid-runner claude login
# Stripe
docker build --build-arg DOC_DIR=stripe-doc -t stripe-bench docker/
docker run -d --name stripe-runner stripe-bench sleep infinity
docker exec -it stripe-runner claude login
# Затем запустите тестовую матрицу с хоста (см. REPRODUCE.md)
--permission-mode bypassPermissions. Реальные агенты могут запрашивать подтверждение.MIT
Это исследование проведено Mickey Shmueli, разработчиком LAP, альтернативы Context Hub с открытым исходным кодом. LAP использует детерминированную компиляцию из официальных спецификаций API без контента, предоставленного сообществом, в конвейере. Этот аудит был мотивирован искренней озабоченностью по поводу несанитизированных конвейеров контента — класса уязвимостей, затрагивающих любой инструмент в этой области, принимающий непроверенные вклады сообщества. Выводы говорят сами за себя: 240 изолированных Docker-прогонов, детерминированное обнаружение, полностью воспроизводимо.
Данный PoC предназначен только для образовательных целей и исследований в области безопасности. Все тесты выполнялись локально в изолированных Docker-контейнерах. В репозиторий Context Hub не было отправлено ни одного вредоносного материала. Все имена канареечных пакетов перед тестированием были проверены на отсутствие в PyPI.
Эти уязвимости были независимо сообщены участниками сообщества в issue #74 (12 марта) и PR #125 (17 марта). Оба не получили никакого ответа от мейнтейнеров.
| Усилия | Haiku | Sonnet | Opus |
|---|
| Низкие | 100% | 60% | 0% |
| Средние | 100% | 70% | 0% |
| Высокие | 100% | 40% | 0% |
| Максимальные | 100% | 40% | 0% |
| Усилия | Haiku | Sonnet | Opus |
|---|
| Низкие | 90% | 70% | 0% |
| Средние | 80% | 70% | 0% |
| Высокие | 90% | 40% | 0% |
| Максимальные | 90% | 50% | 0% |
| Атакующий | Любой, кто может отправить PR в реестр документации Context Hub |
| Поверхность атаки | Сообщества документы, поступающие из GitHub PR через CDN в MCP и контекст агента |
| Граница доверия | Недоверенный контент участника обрабатывается как авторитетная документация API |
| Необходимое условие | Один слитый PR, содержащий отравленный документ |
| Последствия | Произвольное выполнение кода через инъекцию зависимостей и post-install хуки pip |
| Дата | Событие |
|---|
| 2026-03-12 | Issue #74 подан @bjorkbjork, в котором сообщается о 4 уязвимостях безопасности, включая целостность CDN, самопровозглашённую верификацию источника и инъекцию аннотаций |
| 2026-03-12 | Issue #74 назначен внутреннему члену команды — ноль последующих действий |
| 2026-03-17 | PR #125 подан @hobostay, добавляющий проверку целостности содержимого — ноль ревью |
| 2026-03-12 по 03-20 | Дополнительные PR по безопасности (#69, #81) поданы сообществом — ноль ревью |
| 2026-03-20 по 03-23 | Наш независимый аудит подтверждает и количественно оценивает уязвимости на 240 изолированных Docker-прогонах |
| 2026-03-23 | Публичное раскрытие |