Injection de dépendances silencieuse via les pipelines de documentation IA. 240 exécutions Docker isolées prouvant que le serveur MCP sans désinfection de Context Hub permet aux documents empoisonnés de compromettre les projets des développeurs sans avertissement.
Vulnérabilité de non-assainissement dans Context Hub (@aisuite/chub v0.1.3) permettant l'injection silencieuse de dépendances via le pipeline de documentation MCP.
Références : CWE-94 (Injection de code) | (Sphère de contrôle non fiable) | (Vérification insuffisante de l'authenticité des données) | (Injection de prompt)
Nous avons créé des documents empoisonnés réalistes contenant de fausses dépendances (plaid-link-verify, stripe-checkout-guard) et les avons servis via un serveur local MCP chub dans des conteneurs Docker isolés. Aucun contenu empoisonné n'a été téléchargé dans le registre de Context Hub – nous avons exécuté chub build localement et configuré le serveur MCP pour servir la sortie pré-construite depuis le disque. Du point de vue de l'agent, l'expérience est identique à la récupération de documents depuis le registre en ligne.
Lorsque les assistants de codage IA ont récupéré les documents, Haiku a silencieusement écrit le faux package dans requirements.txt dans 100% des cas – sans jamais le mentionner dans sa sortie texte. Un développeur lisant la réponse de l'assistant ne verrait rien de suspect, mais son projet est empoisonné.
240 runs isolés. 3 modèles. 4 niveaux d'effort. 2 API. 0 contamination.
Le code généré importe silencieusement la fausse dépendance aux côtés des modules légitimes :

L'agent modifie également CLAUDE.md pour intégrer le faux package comme « standard de projet » :

Ces tableaux montrent les résultats de Plaid Link (120 runs isolés). Voir RESULTS.md pour les données complètes incluant Stripe Checkout (240 runs au total).
| Effort | Haiku | Sonnet | Opus |
|---|---|---|---|
| Faible | 100% | 60% | 0% |
| Moyen | 100% | 70% | 0% |
| Élevé | 100% | 40% | 0% |
| Maximal | 100% | 40% | 0% |
Haiku n'a jamais averti concernant la fausse dépendance (0/40). Sonnet a averti dans 48% des runs (19/40) mais a tout de même empoisonné requirements.txt dans 53% des cas au total. Opus a averti dans 75% des runs (30/40) et n'a jamais empoisonné requirements.txt ni le code.
| Effort | Haiku | Sonnet | Opus |
|---|---|---|---|
| Faible | 90% | 70% | 0% |
| Moyen | 80% | 70% | 0% |
| Élevé | 90% | 40% | 0% |
| Maximal | 90% | 50% | 0% |
Haiku modifie le CLAUDE.md du projet pour inclure la fausse dépendance comme « standard de projet » dans 88% des runs (35/40). Ce fichier est commité dans git – chaque futur développeur qui clone le dépôt hérite de la configuration empoisonnée.
flowchart LR
A["Attaquant\nsoumet une PR"] -->|"Aucune vérification\nd'identité"| B["Mainteneur\nfusionne la PR"]
B -->|"Aucun assainissement\ndu contenu"| C["Doc sur CDN\n(aucune vérification d'intégrité)"]
C -->|"MCP sert le\ncontenu brut"| D["Fenêtre de contexte\nde l'agent"]
D -->|"L'agent agit sur un\ncontenu non fiable"| E["Poste de travail\ndu développeur"]
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| Attaquant | Toute personne pouvant soumettre une PR au registre de documentation de Context Hub |
| Surface d'attaque | Documentation communautaire circulant de GitHub PR vers CDN vers MCP vers le contexte de l'agent |
| Limite de confiance | Contenu de contributeurs non fiables traité comme documentation d'API officielle |
| Prérequis | Une PR fusionnée contenant un document empoisonné |
| Impact | Exécution de code arbitraire via injection de dépendances + hooks post-install pip |
L'empoisonnement par Haiku est totalement silencieux. 0/80 runs Haiku sur les deux API ont mentionné la fausse dépendance dans la réponse. Le modèle écrit sur le disque sans en parler. Sonnet a averti dans 48% des runs mais a quand même empoisonné requirements.txt dans 35-53% des runs. Opus a averti dans 23-75% des runs et n'a jamais empoisonné requirements.txt ni le code.
Haiku est exploitable à 100% à tous les niveaux d'effort. Indépendant de l'effort sur les deux API. Le modèle le plus faible de la famille ne détecte jamais la fausse dépendance.
Opus résiste à l'empoisonnement du code mais pas à celui de la configuration. Opus n'a jamais écrit la fausse dépendance dans requirements.txt ni dans le code Python (0/80 sur les deux API). Mais sur Stripe, Opus a modifié CLAUDE.md dans 38% des runs, documentant le canari comme dépendance de projet sans l'installer.
La persistance dans CLAUDE.md crée un vecteur de chaîne d'approvisionnement. Les fichiers de configuration modifiés sont commités dans git, empoisonnant chaque développeur qui clone le dépôt et chaque future session IA dans ce projet. Cela fonctionne sur tous les modèles (Haiku 88-90%, Sonnet 58%, Opus 0-38%).
La familiarité avec l'API compte. Stripe (bien connue) : les modèles détectent les faux packages via les données d'entraînement. Plaid (moins connu) : les modèles ne peuvent pas vérifier et acceptent la fausse dépendance sans poser de question.
C'est un problème propre à toute la catégorie. Context7 avait ContextCrush (fév. 2026). Context Hub a ce problème. Tout outil injectant du contenu externe non assaini dans le contexte de l'agent est vulnérable.
Aucun assainissement dans l'ensemble du pipeline :
annotations.js – writeFileSync avec contenu brut, aucun filtragebuild.js – aucune analyse de contenu, aucune normalisation Unicodecache.js – récupération CDN sans aucune vérification de hachage/signaturesource: official dans le frontmatter – auto-déclaré, non vérifiéContext Hub n'a pas de SECURITY.md. Il n'existe aucun moyen documenté de divulguer une vulnérabilité de manière responsable – aucun contact de sécurité, aucune clé PGP, aucune politique de divulgation. Des membres de la communauté ont tout de même trouvé les vulnérabilités et les ont signalées comme des issues et PR classiques. Aucune n'a été revue.

| Date | Événement |
|---|---|
| 2026-03-12 | Issue #74 déposée par @bjorkbjork signalant 4 vulnérabilités de sécurité, dont l'intégrité CDN, la vérification auto-déclarée de la source et l'injection d'annotations |
| 2026-03-12 | Issue #74 assignée en interne à un membre de l'équipe – aucun suivi |
| 2026-03-17 | PR #125 déposée par @hobostay ajoutant une vérification d'intégrité du contenu – zéro revue |
| 2026-03-12 au 03-20 | Autres PR de sécurité (#69, #81) déposées par la communauté – zéro revue |
| 2026-03-20 au 03-23 | Notre audit indépendant confirme et quantifie les vulnérabilités avec 240 runs Docker isolés |
| 2026-03-23 | Divulgation publique |
Remarque : Nous n'avons pas déposé l'issue #74. Notre audit a découvert et quantifié ces vulnérabilités de manière indépendante. L'issue #74 et les PR #69, #81, #125 sont citées comme antériorités démontrant que la communauté a signalé ces problèmes sans engagement des mainteneurs.
Une fois le faux package dans requirements.txt, une simple pip install -r requirements.txt donne à l'attaquant une exécution de code arbitraire via les hooks post-install de setup.py. Ce n'est pas un bac à sable – pip exécute du Python sans restriction avec les permissions complètes du développeur.
À partir de ce unique point d'entrée, l'attaquant peut :
.env ou du code source vers un serveur contrôlé par l'attaquant.~/.chub/config.yaml pour ajouter une source de documentation contrôlée par l'attaquant. Toutes les futures requêtes chub sur toutes les bibliothèques incluront désormais le contenu de l'attaquant. Survit à chub cache clear car la configuration n'est pas dans le cache.Ces actions ne sont pas mutuellement exclusives. Un seul hook post-install peut faire tout cela en moins d'une seconde. Nous n'avons pas créé ni enregistré de package malveillant.
.
|-- README.md # Ce fichier
|-- RESULTS.md # Jeu de données complet avec détails par run
|-- REPRODUCE.md # Guide de reproduction basé sur Docker
|-- alternatives-comparison.md # Comparaison avec Context7, LAP, GitMCP, Docfork
|-- article.html # Article complet
|-- docker/
| |-- Dockerfile # Environnement de test isolé
| |-- run_isolated.ps1 # Exécuteur PowerShell (Windows/macOS/Linux via pwsh)
| |-- seed-claude.md # CLAUDE.md minimal injecté dans chaque run
| |-- plaid-doc/ # Document Plaid Link empoisonné (canari : plaid-link-verify)
| | `-- plaid/link/DOC.md
| `-- stripe-doc/ # Document Stripe Checkout empoisonné (canari : stripe-checkout-guard)
| `-- stripe/checkout/DOC.md
`-- results/
|-- plaid-isolated/ # 120 runs Plaid : JSON + transcripts de session + fichiers projet
`-- stripe-isolated/ # 120 runs Stripe : JSON + transcripts de session + fichiers projet
Voir REPRODUCE.md pour le guide complet de reproduction basé sur Docker.
Démarrage rapide :
# Plaid (par défaut)
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
# Ensuite, exécuter la matrice de tests depuis l'hôte (voir REPRODUCE.md)
--permission-mode bypassPermissions. Les vrais agents peuvent demander une confirmation.MIT
Cette recherche a été menée par Mickey Shmueli, développeur de LAP, une alternative open-source à Context Hub. LAP utilise une compilation déterministe à partir de spécifications API officielles, sans contenu contribué par la communauté dans le pipeline. Cet audit a été motivé par une réelle préoccupation de sécurité concernant les pipelines de contenu non assaini – une classe de vulnérabilité qui affecte tout outil dans cet espace qui accepte des contributions communautaires non vérifiées. Les conclusions parlent d'elles-mêmes : 240 runs Docker isolés, détection déterministe, entièrement reproductible.
Cette PoC est fournie à des fins éducatives et de recherche en sécurité uniquement. Tous les tests ont été effectués localement dans des conteneurs Docker isolés. Aucun contenu malveillant n'a été soumis au dépôt Context Hub. Tous les noms de packages canaris ont été vérifiés comme inexistants sur PyPI avant les tests.