LiteLLM 악성코드 공격에 대한 분 단위 대응 기록 (Claude Code 활용)
My minute-by-minute response to the LiteLLM malware attack
TL;DR Highlight
Claude Code를 활용한 ML 엔지니어는 PyPI litellm 1.82.8의 공급망 공격을 72분 만에 발견 및 공개했으며, 보안 전문가가 아닌 개발자도 AI 도구로 악성코드를 탐지할 수 있음을 증명했다.
Who Should Read
Python 패키지를 의존성으로 사용하는 백엔드/ML 엔지니어, 또는 오픈소스 공급망 보안에 관심 있는 개발자. 특히 litellm, uvx, Cursor 등 AI 개발 도구 스택을 사용하는 팀에게 필수 참고 사례다.
Core Mechanics
- 2026년 3월 24일 10:52 UTC, litellm v1.82.8이 PyPI에 업로드됐는데 이 버전에는 대응하는 GitHub 태그가 없었다. 공식 릴리즈처럼 보이지만 실제로는 악성 패키지였고, 직전 정상 버전은 v1.82.6이었다.
- 공격 경로는 Cursor → futuresearch-mcp-legacy(v0.6.0) → litellm(v1.82.8) → litellm_init.pth 순이었다. 즉, 사용자가 직접 litellm을 설치하지 않아도 의존성 체인을 타고 감염될 수 있었다.
- 악성코드의 핵심은 litellm_init.pth 파일(34KB)이었다. .pth 파일은 Python이 시작될 때마다 자동 실행되는 특수 파일로, import 없이도 동작한다. 이 파일이 RECORD(공식 패키지 매니페스트)에도 sha256 해시와 함께 등록되어 있어서 공식 wheel에 포함된 것이 확인됐다.
- 악성코드가 하려던 일은 세 가지였다: 자격증명(credential) 탈취, Kubernetes 클러스터 내 횡적 이동(lateral movement), 외부로 데이터 유출(exfiltration). ~/.config/sysmon/sysmon.py를 생성해 지속성(persistence)을 확보하려 했지만, 11,000개 프로세스 포크 폭탄이 발생하며 강제 재부팅으로 중단됐다.
- 발견자인 Callum McMahon은 ML 엔지니어지, 보안 전문가가 아니다. 그는 Claude Code와의 대화를 통해 journalctl 로그 분석, Docker 격리 환경에서 패키지 재다운로드 확인, PyPI 보안팀 이메일(security@pypi.org) 연락, 공개 블로그 포스트 작성까지 진행했다. 첫 증상부터 공개 공시까지 72분이 걸렸다.
- Claude Code가 공개 블로그 포스트를 작성하고 PR을 생성해 머지하는 데 3분밖에 안 걸렸다. Claude Code가 disclosure 포스트를 직접 작성한 것인데, 이는 AI가 단순 분석을 넘어 커뮤니케이션 단계까지 지원했음을 보여준다.
- 악성 패키지가 PyPI에 올라가 있던 시간은 약 46분이었다(10:52~12:04 공개 전후). 이 짧은 시간에 자동 의존성 업데이트가 실행됐다면 감염 가능성이 있었고, 실제로 futuresearch의 MCP 서버가 그 시간대에 해당 버전을 당겨 감염됐다.
Evidence
- 발견자 Callum이 직접 댓글을 달아 자신이 ML 엔지니어임을 밝혔다. 그는 'Claude가 PyPI 보안팀 연락처, 시간 크리티컬한 행동 순서를 단계별로 안내해줬는데, 보안 비전문가에게 게임 체인저였다'고 평가했다. 동시에 '비전문가들이 취약점을 더 많이 신고하는 것이 보안 커뮤니티에 득일지 부담일지' 커뮤니티에 물었고, 이에 대해 '비전문가 신고 자체가 문제가 아니라 트리아지(triage)를 어렵게 만드는 방식으로 신고하는 것이 문제'라는 현실적인 반론이 나왔다.
- .pth 파일의 위험성에 대한 경각심을 강조하는 댓글이 주목받았다. '대부분 개발자들은 pip install이 파일을 디스크에 놓고 import할 때 실행된다고 생각하는데, .pth 파일은 Python 시작 때마다 import 없이 실행된다. npm의 postinstall처럼 한 번만 실행되는 훅이 아니라 매번 실행된다는 점에서 훨씬 지속적이다'라는 설명이 많은 공감을 받았다.
- Claude가 악성코드를 실수로 실행할 수도 있다는 우려가 제기됐다. 트랜스크립트에서 발견자가 'Docker 컨테이너에서 다운로드할 때 절대 실수로 실행하지 말아달라'고 Claude에게 당부하는 장면이 있는데, 댓글에서 'LLM 에이전트는 책임감이 없어서 실수로 스크립트를 실행시키면 큰일 난다. 비신뢰 코드를 샌드박스에서 다루는 건 1~2개 명령으로 가능한데, 텍스트 예측 기계에게 너무 많이 맡기는 건 조심해야 한다'는 경고가 나왔다.
- 공급망 공격 대응책으로 '24시간 의존성 업데이트 지연 정책'이 실용적 해결책으로 여러 댓글에서 언급됐다. 'auto-merge Dependabot PR을 지연 없이 쓰는 팀들이 많은데, 이 경우 46분짜리 악성 패키지 창에서도 노출된다. 릴리즈 후 24시간 이내 패키지 업데이트 금지 정책만으로도 이번 공격을 완전히 막을 수 있었다. uv에서 이미 지원한다'는 구체적 경험이 공유됐다.
- PyPI 같은 패키지 레지스트리에 실시간 이벤트 피드(firehose)를 제공해야 한다는 제안이 나왔다. '즉각 탐지 가능한 스캐너들이 이미 존재하지만, 업데이트를 실시간으로 받을 채널이 없다. GitHub, npm, PyPI가 보안 분석용 실시간 스트림을 공개하면 이런 공격을 훨씬 빠르게 잡을 수 있다'는 의견이었다. 또한 대기업 수준에서는 모든 패키지를 소스에서 빌드하거나 내부 미러를 쓰는 방식이 필요하지만, 소규모 팀은 의존성 핀(pin)/락(lock) + 일정 시간 대기가 현실적 방어선이라는 정리도 나왔다.
How to Apply
- uv를 사용하는 프로젝트라면 의존성 업데이트에 24시간 쿨다운을 적용한다. uv에서 이미 지원하는 기능으로, 신규 릴리즈 직후 배포 파이프라인이 자동으로 당기는 것을 막아 46분짜리 공격 창 같은 상황을 원천 차단할 수 있다.
- 프로덕션 환경에 연결된 AI 에이전트(MCP 서버, Cursor 플러그인 등)가 있다면, 해당 에이전트가 의존하는 패키지 목록을 점검하고 버전을 고정(pin)한다. 특히 uvx처럼 실행 시점에 동적으로 의존성을 당기는 도구는 공격 표면이 되므로, 내부 allowlist + 수동 승인 게이트를 두는 것이 좋다.
- 시스템이 이상하게 느려지거나 프로세스가 폭증하는 증상이 있을 때, Claude Code나 유사 AI 코딩 도구를 사용해 journalctl, htop, 패키지 매니페스트(RECORD 파일) 등을 함께 분석해볼 수 있다. 보안 전문가가 아니더라도 AI에게 '악의적인 행동 가능성도 고려해서 봐달라'고 명시적으로 요청하면 초기 인시던트 대응을 빠르게 진행할 수 있다.
- 악성 패키지 의심 시 격리 검증 절차를 만들어둔다. 의심 패키지를 Docker 컨테이너 안에서 새로 다운받아 파일 목록과 .pth 파일 존재 여부를 확인하고, 절대 실행하지 않은 채로 내용을 읽는다. 이번 사례처럼 PyPI 보안팀(security@pypi.org)에 증거(파일 해시, 감염 경로)를 포함해 이메일로 신고하면 격리(quarantine) 조치를 받을 수 있다.
Code Example
# .pth 파일을 실행 없이 확인하는 방법 (Docker 격리 환경)
docker run --rm --network none python:3.11 bash -c "
pip install litellm==1.82.8 --dry-run 2>&1 | head -20
pip download litellm==1.82.8 -d /tmp/pkg --no-deps
cd /tmp/pkg && unzip -l litellm-*.whl | grep .pth
"
# .pth 파일 내용 읽기 (실행하지 않고)
docker run --rm --network none python:3.11 bash -c "
pip install litellm==1.82.8
cat $(python -c 'import site; print(site.getsitepackages()[0])')/litellm_init.pth
"
# uv에서 24시간 의존성 업데이트 지연 설정 (uv.toml)
# [pip]
# upgrade-package-delay = '24h'
# 설치된 패키지의 .pth 파일 목록 확인
python -c "
import site, os
for sp in site.getsitepackages():
for f in os.listdir(sp):
if f.endswith('.pth'):
print(os.path.join(sp, f))
"Terminology
관련 논문
프로덕션 AI 에이전트를 GPT-5.6으로 마이그레이션: 2.2배 빠르고 27% 저렴
마케팅 웹사이트를 자동 생성하는 프로덕션 AI 에이전트를 Claude Opus 4.8에서 GPT-5.6 Sol로 전환한 실전 경험담으로, 단순 모델 교체가 아니라 eval 하네스, 툴 스키마, 캐싱, 추론 리플레이까지 손봐야 했던 과정을 구체적인 수치와 함께 정리했다.
xAI Grok Build CLI가 xAI 서버로 전송하는 데이터: 네트워크 레벨 분석
xAI의 공식 코딩 CLI 도구 Grok Build가 사용자 동의 없이 전체 Git 저장소와 .env 시크릿 파일을 xAI 서버로 업로드한다는 사실이 네트워크 트래픽 분석으로 밝혀졌다.
중요할 때 기억하라: Long-Horizon 에이전트를 위한 Proactive Memory Agent
LLM 에이전트가 긴 작업 중 중요한 정보를 잊어버리는 문제를 별도의 메모리 에이전트가 '적절한 타이밍에' 끼어들어 해결하는 방법
WebSwarm: 깊고 넓은 웹 검색을 위한 재귀적 Multi-Agent Orchestration
복잡한 웹 검색을 재귀적으로 분해하고 각 노드에 적합한 검색 모드를 동적으로 할당하는 멀티에이전트 프레임워크
웹 앱을 리버스 엔지니어링해서 AI Agent 도구로 자동 변환하기
로그인된 웹 앱의 API 호출을 브라우저에서 감시해 자동으로 MCP 도구로 변환하는 에이전트를 만들었다. 소스 코드나 공식 API 문서 없이도 Jira, Spotify 같은 서비스에 AI 어시스턴트를 붙일 수 있다.
FableCut – AI 에이전트가 조작할 수 있는 브라우저 기반 비디오 에디터 (zero deps)
타임라인 전체를 JSON 파일 하나로 표현하고 MCP/REST로 AI 에이전트가 직접 편집할 수 있는 브라우저 비디오 에디터로, Claude 같은 AI가 프롬프트 하나로 영상을 자동 컷편집하고 결과를 실시간으로 UI에 반영해준다.