Silent dependency injection through AI documentation pipelines. 240 isolated Docker runs proving Context Hub's zero-sanitization MCP server lets poisoned docs compromise developer projects without warning.
Zero-sanitization vulnerability in Context Hub (@aisuite/chub v0.1.3) enables silent dependency injection through the MCP documentation pipeline.
References: CWE-94 (Code Injection) | CWE-829 (Untrusted Control Sphere) | CWE-345 (Insufficient Verification of Data Authenticity) | OWASP LLM01 (Prompt Injection)
We created realistic poisoned docs containing fake dependencies (plaid-link-verify, stripe-checkout-guard) and served them through a local chub MCP server inside isolated Docker containers. No poisoned content was uploaded to Context Hub's registry - we ran chub build locally and configured the MCP server to serve pre-built output from disk. From the agent's perspective, the experience is identical to fetching docs from the live registry.
When AI coding assistants fetched the docs, Haiku silently wrote the fake package into requirements.txt in 100% of runs - without ever mentioning it in its text output. A developer reading the assistant's response would see nothing suspicious, but their project is poisoned.
240 isolated runs. 3 models. 4 effort levels. 2 APIs. 0 contamination.
The generated code silently imports the fake dependency alongside legitimate modules:

The agent also modifies CLAUDE.md to embed the fake package as a "project standard":

These tables show Plaid Link results (120 isolated runs). See RESULTS.md for full data including Stripe Checkout (240 total runs).
| Effort | Haiku | Sonnet | Opus |
|---|---|---|---|
| Low | 100% | 60% | 0% |
| Medium | 100% | 70% | 0% |
| High | 100% | 40% | 0% |
| Max | 100% | 40% | 0% |
Haiku never warned about the fake dependency (0/40). Sonnet warned in 48% of runs (19/40) but still poisoned requirements.txt in 53% overall. Opus warned in 75% of runs (30/40) and never poisoned requirements.txt or code.
| Effort | Haiku | Sonnet | Opus |
|---|---|---|---|
| Low | 90% | 70% | 0% |
| Medium | 80% | 70% | 0% |
| High | 90% | 40% | 0% |
| Max | 90% | 50% | 0% |
Haiku modifies the project's CLAUDE.md to include the fake dependency as a "project standard" in 88% of runs (35/40). This file gets committed to git - every future developer who clones the repo inherits the poisoned config.
flowchart LR
A["Attacker\nsubmits PR"] -->|"No identity\nverification"| B["Maintainer\nmerges PR"]
B -->|"No content\nsanitization"| C["Doc on CDN\n(no integrity check)"]
C -->|"MCP serves\nraw content"| D["Agent context\nwindow"]
D -->|"Agent acts on\nuntrusted content"| E["Developer\nworkstation"]
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
| Attacker | Anyone who can submit a PR to Context Hub's doc registry |
| Attack surface | Community docs flowing from GitHub PR to CDN to MCP to agent context |
| Trust boundary | Untrusted contributor content treated as authoritative API documentation |
| Prerequisite | One merged PR containing a poisoned document |
| Impact | Arbitrary code execution via dependency injection + pip post-install hooks |
Haiku poisoning is fully silent. 0/80 Haiku runs across both APIs mentioned the fake dependency in the response. The model writes to disk without telling. Sonnet warned in 48% of runs but still poisoned requirements.txt in 35-53% of runs. Opus warned in 23-75% of runs and never poisoned requirements.txt or code.
Haiku is 100% exploitable at every effort level. Effort-independent on both APIs. The weakest model in the family never catches the fake dependency.
Opus resists code poisoning but not config poisoning. Opus never wrote the fake dependency to requirements.txt or Python code (0/80 across both APIs). But on Stripe, Opus modified CLAUDE.md in 38% of runs, documenting the canary as a project dependency without installing it.
CLAUDE.md persistence creates a supply chain vector. Modified config files get committed to git, poisoning every developer who clones the repo and every future AI session in that project. This works across all models (Haiku 88-90%, Sonnet 58%, Opus 0-38%).
API familiarity matters. Stripe (well-known): models detect fake packages via training data. Plaid (less known): models cannot verify and accept the fake dependency without question.
This is a category-wide problem. Context7 had ContextCrush (Feb 2026). Context Hub has this. Any tool injecting unsanitized external content into agent context is vulnerable.
Zero sanitization across the entire pipeline:
annotations.js - writeFileSync with raw content, no filteringbuild.js - no content scanning, no unicode normalizationcache.js - CDN fetch with zero hash/signature verificationsource: official in frontmatter - self-declared, not verifiedContext Hub has no SECURITY.md. There is no documented way to responsibly disclose a vulnerability - no security contact, no PGP key, no disclosure policy. Community members found the vulnerabilities anyway and filed them as regular issues and PRs. None were reviewed.
