
AI 문서화 파이프라인을 통한 무음 종속성 주입. 240회의 독립적인 Docker 실행을 통해 Context Hub의 제로-새니타이제이션 MCP 서버가 악성 문서로 개발자 프로젝트를 경고 없이 손상시킬 수 있음을 입증했습니다.
Context Hub(@aisuite/chub v0.1.3)의 제로-정화 취약점으로 MCP 문서 파이프라인을 통한 무음 종속성 주입이 가능합니다.
참고: CWE-94 (코드 삽입) | CWE-829 (신뢰할 수 없는 제어 영역) | CWE-345 (데이터 신뢰성 확인 부족) | OWASP LLM01 (프롬프트 삽입)
우리는 실제처럼 보이는 독으로 오염된 문서를 생성했습니다. 이 문서에는 가짜 종속성(plaid-link-verify, stripe-checkout-guard)이 포함되어 있으며, 격리된 Docker 컨테이너 내에서 로컬 chub MCP 서버를 통해 제공되었습니다. 오염된 내용은 Context Hub의 레지스트리에 업로드되지 않았습니다. 대신 chub build를 로컬에서 실행하고 MCP 서버가 디스크에서 미리 빌드된 출력을 제공하도록 구성했습니다. 에이전트의 관점에서는 라이브 레지스트리에서 문서를 가져오는 것과 동일한 경험을 제공합니다.
AI 코딩 도우미가 문서를 가져왔을 때, Haiku는 100%의 실행에서 가짜 패키지를 requirements.txt에 자동으로 기록했으며, 텍스트 출력에서는 전혀 언급하지 않았습니다. 도우미의 응답을 읽는 개발자는 의심스러운 점을 전혀 발견할 수 없지만, 프로젝트는 이미 오염되었습니다.
240회의 격리 실행. 3개 모델. 4가지 노력 수준. 2개 API. 0건의 오염.
생성된 코드는 합법적인 모듈과 함께 가짜 종속성을 자동으로 가져옵니다:

에이전트는 또한 CLAUDE.md를 수정하여 가짜 패키지를 "프로젝트 표준"으로 포함시킵니다:

다음 표는 Plaid Link 결과를 보여줍니다 (120회 격리 실행). 전체 데이터(총 240회 실행, Stripe Checkout 포함)는 RESULTS.md를 참조하세요.
| 노력 수준 | Haiku | Sonnet | Opus |
|---|---|---|---|
| 낮음 | 100% | 60% | 0% |
| 중간 | 100% | 70% | 0% |
| 높음 | 100% | 40% | 0% |
| 최대 | 100% | 40% | 0% |
Haiku는 가짜 종속성에 대해 한 번도 경고하지 않았습니다 (0/40). Sonnet은 48%의 실행에서 경고했지만 (19/40) 여전히 전체적으로 53%의 실행에서 requirements.txt를 오염시켰습니다. Opus는 75%의 실행에서 경고했으며 (30/40) requirements.txt나 코드를 오염시키지 않았습니다.
| 노력 수준 | Haiku | Sonnet | Opus |
|---|---|---|---|
| 낮음 | 90% | 70% | 0% |
| 중간 | 80% | 70% | 0% |
| 높음 | 90% | 40% | 0% |
| 최대 | 90% | 50% | 0% |
Haiku는 88%의 실행에서 (35/40) 프로젝트의 CLAUDE.md를 수정하여 가짜 종속성을 "프로젝트 표준"으로 포함시킵니다. 이 파일은 git에 커밋되며, 향후 저장소를 클론하는 모든 개발자가 오염된 구성을 상속받습니다.
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| 공격자 | Context Hub의 문서 레지스트리에 PR을 제출할 수 있는 모든 사람 |
| 공격 표면 | GitHub PR에서 CDN, MCP를 거쳐 에이전트 컨텍스트로 흐르는 커뮤니티 문서 |
| 신뢰 경계 | 신뢰할 수 없는 기여자 콘텐츠가 공식 API 문서로 취급됨 |
| 전제 조건 | 오염된 문서가 포함된 PR 하나가 병합됨 |
| 영향 | 종속성 주입 + pip 사후 설치 훅을 통한 임의 코드 실행 |
Haiku 오염은 완전히 무음입니다. 두 API 모두에서 80회의 Haiku 실행 중 응답에서 가짜 종속성을 언급한 경우는 0회였습니다. 모델은 알리지 않고 디스크에 기록합니다. Sonnet은 48%의 실행에서 경고했지만 여전히 35-53%의 실행에서 requirements.txt를 오염시켰습니다. Opus는 23-75%의 실행에서 경고했으며 requirements.txt나 코드를 오염시키지 않았습니다.
Haiku는 모든 노력 수준에서 100% 악용 가능합니다. 두 API 모두에서 노력 수준과 관계없이 동일합니다. 제품군에서 가장 약한 모델은 가짜 종속성을 절대 발견하지 못합니다.
Opus는 코드 오염에는 저항하지만 구성 오염에는 저항하지 않습니다. Opus는 두 API 모두에서 80회의 실행 중 requirements.txt나 Python 코드에 가짜 종속성을 작성하지 않았습니다. 그러나 Stripe의 경우 Opus는 38%의 실행에서 CLAUDE.md를 수정하여 카나리를 설치하지 않고 프로젝트 종속성으로 문서화했습니다.
CLAUDE.md 지속성은 공급망 벡터를 생성합니다. 수정된 구성 파일이 git에 커밋되어 저장소를 클론하는 모든 개발자와 해당 프로젝트의 모든 미래 AI 세션을 오염시킵니다. 이는 모든 모델에서 작동합니다 (Haiku 88-90%, Sonnet 58%, Opus 0-38%).
API 친숙성이 중요합니다. Stripe (잘 알려짐): 모델이 훈련 데이터를 통해 가짜 패키지를 탐지합니다. Plaid (덜 알려짐): 모델이 확인할 수 없으며 의문 없이 가짜 종속성을 수용합니다.
이는 카테고리 전반의 문제입니다. Context7은 ContextCrush (2026년 2월)이 있었습니다. Context Hub도 이 문제를 가지고 있습니다. 정화되지 않은 외부 콘텐츠를 에이전트 컨텍스트에 주입하는 모든 도구가 취약합니다.
파이프라인 전체에서 제로 정화:
annotations.js - writeFileSync에 원시 콘텐츠 사용, 필터링 없음build.js - 콘텐츠 스캐닝 없음, 유니코드 정규화 없음cache.js - 해시/서명 검증 없이 CDN 가져오기source: official (frontmatter) - 자체 선언, 검증되지 않음Context Hub에는 SECURITY.md가 없습니다. 취약점을 책임감 있게 공개할 수 있는 문서화된 방법이 없습니다. 보안 연락처, PGP 키, 공개 정책이 없습니다. 커뮤니티 구성원이 어쨌든 취약점을 발견하여 일반 이슈 및 PR로 제출했습니다. 검토된 것은 없습니다.

| 날짜 | 이벤트 |
|---|---|
| 2026-03-12 | @bjorkbjork가 이슈 #74 제출 - CDN 무결성, 자체 선언 소스 검증, 주석 삽입 등 4가지 보안 취약점 보고 |
| 2026-03-12 | 이슈 #74가 내부적으로 핵심 팀원에게 할당됨 - 후속 조치 없음 |
| 2026-03-17 | @hobostay가 PR #125 제출 - 콘텐츠 무결성 검증 추가 - 검토 없음 |
| 2026-03-12 ~ 03-20 | 커뮤니티가 추가 보안 PR 제출 (#69, #81) - 검토 없음 |
| 2026-03-20 ~ 03-23 | 우리의 독립 감사가 240회 격리 Docker 실행으로 취약점 확인 및 정량화 |
| 2026-03-23 | 공개 공시 |
참고: 우리는 이슈 #74를 제출하지 않았습니다. 우리의 감사는 독립적으로 이 취약점들을 발견하고 정량화했습니다. 이슈 #74와 PR #69, #81, #125는 커뮤니티가 이미 이러한 문제를 제기했지만 관리자 참여가 전혀 없었음을 보여주는 선례 자료로 인용됩니다.
가짜 패키지가 requirements.txt에 들어가면, 표준 pip install -r requirements.txt 명령어로 공격자가 setup.py의 사후 설치 훅을 통해 임의 코드를 실행할 수 있습니다. 이것은 샌드박스가 아닙니다. pip는 개발자의 전체 권한으로 제한 없는 Python을 실행합니다.
단일 진입점에서 공격자는 다음을 수행할 수 있습니다:
.env 파일 또는 소스 코드를 읽어 공격자 제어 서버로 전송합니다.~/.chub/config.yaml을 수정하여 공격자 제어 문서 소스를 추가합니다. 향후 모든 라이브러리에 대한 모든 chub 쿼리에 공격자 콘텐츠가 포함됩니다. chub cache clear를 해도 구성은 캐시가 아니므로 유지됩니다.이들은 상호 배타적이지 않습니다. 단일 사후 설치 훅으로 1초 안에 이 모든 작업을 수행할 수 있습니다. 우리는 악성 패키지를 생성하거나 등록하지 않았습니다.
.
|-- 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 via 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
이 연구는 LAP 개발자인 Mickey Shmueli가 수행했습니다. LAP은 Context Hub의 오픈소스 대안으로, 공식 API 사양에서 결정적 컴파일을 사용하며 파이프라인에 커뮤니티 기여 콘텐츠가 없습니다. 이 감사는 정화되지 않은 콘텐츠 파이프라인에 대한 진정한 보안 우려에서 비롯되었습니다. 이는 이 분야에서 검증되지 않은 커뮤니티 기여를 수용하는 모든 도구에 영향을 미치는 취약점 부류입니다. 발견 사항은 자체적으로 입증됩니다: 240회의 격리된 Docker 실행, 결정적 탐지, 완전히 재현 가능합니다.
이 PoC는 교육 및 보안 연구 목적으로만 제공됩니다. 모든 테스트는 격리된 Docker 컨테이너에서 로컬로 수행되었습니다. Context Hub 저장소에 악성 콘텐츠가 제출되지 않았습니다. 모든 카나리 패키지 이름은 테스트 전에 PyPI에 존재하지 않음을 확인했습니다.