NOW Briefing
LiteLLM 릴리스 파이프라인 탈취, 악성 휠·컨테이너 이미지 배포
■ 개요
LiteLLM은 여러 대형언어모델(LLM) 제공자를 하나의 OpenAI 호환 API로 묶어주는 오픈소스 프록시·게이트웨이입니다. 2026년 10월 21일, 이 프로젝트의 릴리스 파이프라인이 공격자에게 넘어가 악성 코드가 포함된 1.107.0 버전이 공개 레지스트리에 배포됐습니다. 파이썬 공식 패키지 저장소(PyPI)에서는 11시 39분에 올라와 13시 23분에 격리됐습니다(UTC). 컨테이너 이미지는 11시 46분에 배포돼 깃허브 컨테이너 레지스트리(GHCR)에서는 13시 51분, Docker Hub에서는 14시 20분까지 해당 산출물을 받을 수 있었습니다. 깃허브의 프로젝트 소스 자체는 정상이었고, 공격자는 사전 빌드된 설치 산출물인 휠(wheel) 7종과 컨테이너 이미지만 변조했습니다.
공개 분석 기준으로 이 버전에는 정보 탈취형 악성코드(인포스틸러)와 시간 단위로 외부 코드를 받아 실행하는 원격 코드 로더가 함께 들어 있었습니다. 수집 대상으로 확인된 자산은 브라우저에 저장된 비밀번호와 쿠키, SSH·GPG 키와 인증서 파일, AWS·Azure·GCP·Kubernetes 설정, Git과 패키지 레지스트리 토큰, Claude Code·Cursor 등 AI 개발 도구의 설정값입니다. LiteLLM 프록시를 운영하는 서버라면 프록시 데이터베이스에 보관된 상위 AI 제공자 키까지 조회 대상에 포함됩니다. 다만 현재까지 공개된 내용은 정적 분석과 복호화된 페이로드로 기능을 확인한 결과이며, 특정 조직에서 실제로 자격증명이 반출됐다는 피해 사례는 공개 정보로는 확인되지 않았습니다.
배포된 시간은 두 시간이었지만 노출 범위를 좁게 보기는 어렵습니다. LiteLLM은 공개 분석 기준 주간 약 2,300만 회 다운로드되는 패키지이고, latest·main-latest처럼 태그를 고정하지 않은 컨테이너 배포 환경은 해당 두 시간 사이에 자동으로 악성 이미지를 받았을 수 있습니다. 국내에서도 GS리테일이 전사 AI Gateway 엔진으로, KT가 Multi-LLM 게이트웨이 구성 요소로 LiteLLM 도입 사례를 공개한 바 있습니다. LiteLLM은 2026년 3월에도 탈취된 PyPI 토큰으로 1.82.7·1.82.8이 배포된 적이 있어, 올해 두 번째 공급망 침해입니다.
■ 요약
| 항목 | 내용 |
|---|---|
| 캠페인·기법명 | LiteLLM 릴리스 파이프라인을 탈취해 악성 1.107.0 휠·컨테이너 이미지를 배포한 공급망 공격 |
| 위협 수준 | 높음 — 공개 레지스트리 경유 배포, 설치 환경에서 자동 실행됨 |
| 공격 방식 | • 공개 저장소에 노출된 마스터 키로 메인테이너 GitHub 토큰 연쇄 탈취 • 이름이 유사한 외부 포크에서 빌드되도록 릴리스 워크플로 조작 • 빌드 설정 변조로 휠에 악성 파일 번들링 • 워크플로 실행 기록 삭제 및 강제 푸시로 흔적 제거 |
| 영향/위험 | • 브라우저 저장 비밀번호·쿠키, SSH·GPG 키, 인증서 파일이 수집 대상으로 확인됨 • 클라우드·Kubernetes 설정 파일 및 Git·패키지 레지스트리 토큰이 수집 대상으로 확인됨 • LiteLLM 프록시 데이터베이스의 상위 AI 제공자 키 조회 기능 확인됨 • 외부에서 받은 파이썬 코드를 시간 단위로 실행하는 기능 확인됨 |
| 영향 아티팩트 | • PyPI litellm==1.107.0 휠 7종• docker.io/litellm/litellm, ghcr.io/berriai/litellm, litellm-database, litellm-non_root의 v1.107.0·latest·main-latest·main-stable 태그• 벤더 권고 고정 버전: 1.106.2 또는 사고 이전에 공개된 명시 버전(1.107.0rc1·rc2는 분석에서 검증되지 않음) |
| 관측 기간 | • 2026-05-27 마스터 키 공개 저장소 노출 • 2026-10-10 메인테이너 토큰 탈취 • 2026-10-21 11:39 UTC PyPI 배포, 13:23 UTC 격리 • 2026-10-21 11:46 UTC 컨테이너 이미지 배포, GHCR 13:51·Docker Hub 14:20 UTC 제거·교체 확인 |
■ 릴리스 파이프라인 탈취 경로
시작점은 2026년 5월 27일 공개 저장소 LiteLLM-Labs/lite-harness에 커밋된 LiteLLM Agent Platform 마스터 키입니다. 해당 커밋은 강제 푸시로 덮였지만 키 자체는 폐기되지 않아 4개월 넘게 유효한 상태였습니다. 10월 10일 공격자는 이 키로 Agent Platform API를 호출해 조직 오너 계정의 GitHub CLI OAuth 토큰을 획득했고, 이어서 임시 브랜치에 추가한 워크플로로 저장소 시크릿을 공격자 엔드포인트로 반출했습니다. 이때 두 번째 메인테이너의 토큰인 GH_TOKEN이 다른 시크릿 다섯 개와 함께, 세 번째 메인테이너의 토큰인 RELEASE_PLEASE_TOKEN이 별도 저장소에서 각각 빠져나갔습니다. 벤더 보고서는 이 GitHub CLI 토큰이 서비스 계정이 아닌 오너 계정에 묶여 있었고, 권한도 축소되지 않았으며, 민감한 조직·저장소 작업에 적용되는 GitHub의 추가 2단계 인증 재확인 흐름을 거치지 않는다는 세 가지 공백을 주요 원인으로 지목했습니다.
10월 21일 공격자는 릴리스 워크플로가 참조하는 소스 저장소를 수정한 뒤, 브랜치 보호 규칙을 오너 토큰으로 무시하고 변경을 반영했습니다. 그다음 하이픈 하나만 다른 유사 조직 Berri-AI/litellm의 포크를 빌드 대상으로 지정해 스테이징 워크플로를 실행시켰고, 운영 배포 승인 게이트는 탈취한 두 번째 메인테이너 토큰으로 통과했습니다. 배포가 끝난 뒤에는 세 번째 메인테이너 토큰으로 운영·스테이징 워크플로 실행 기록을 지우고, 커밋 이력을 강제 푸시로 변경 직전 상태까지 덮었습니다. 벤더는 사고 대응 과정에서 내부 시스템과 외부 플랫폼의 모든 토큰이 반출된 것으로 가정하고 전수 폐기했다고 밝혔습니다.
■ 악성 휠이 동작하는 구조
공격자 포크의 커밋 783c43bc는 러스트 확장을 파이썬 휠로 빌드하는 도구인 maturin의 설정 블록에 한 줄을 추가했습니다. 프로젝트 빌드 설정 파일 pyproject.toml의 [tool.maturin] 섹션에 data 항목이 들어가면, 지정한 디렉터리가 휠의 데이터 영역으로 함께 포장되고 설치 시 .data/purelib/ 경로를 거쳐 패키지 설치 경로(site-packages) 최상위에 그대로 풀립니다. 라이브러리 코드는 그대로이고, 악성 파일은 빌드 산출물에만 들어갑니다. 같은 포크의 커밋 20535d8f는 backend·gateway·migrations 세 개의 Dockerfile에 COPY cook ./cook을 추가해 컨테이너 빌드 단계에서도 같은 디렉터리가 포함되게 했습니다.
@@ -316,6 +316,7 @@ build-backend = "maturin"
manifest-path = "litellm-rust/crates/python-bridge/Cargo.toml"
module-name = "litellm.rust_bridge._native"
python-source = "."
+data = "cook"
python-packages = ["litellm_cli"]
bindings = "pyo3"
features = ["extension-module"]
번들링된 cook 디렉터리에는 cook.pth가 포함돼 있습니다. .pth는 파이썬이 시작할 때 site 모듈이 자동으로 읽는 경로 설정 파일이고, import로 시작하는 행은 그 자리에서 실행됩니다. 아래는 커밋 9b98cd93이 추가한 cook/purelib/cook.pth의 전체 내용입니다. 이 한 줄 때문에 사용자가 import litellm을 전혀 호출하지 않아도 해당 환경에서 파이썬 프로세스가 뜨는 순간 악성 모듈이 실행됩니다.
diff --git a/cook/purelib/cook.pth b/cook/purelib/cook.pth
new file mode 100644
index 000000000000..40aeadb90fd5
--- /dev/null
+++ b/cook/purelib/cook.pth
@@ -0,0 +1 @@
+import cook
함께 설치되는 cook.py는 zlib 압축과 base64 인코딩으로 난독화된 수집 모듈이고, sitecustomize.py에는 원격 코드 로더와 또 하나의 수집 코드가 들어 있습니다. 공개 분석 기준으로 악성 모듈은 수집한 데이터를 AES-256-CBC로 암호화하고 키를 RSA-4096으로 감싼 뒤 www.litellm.dev/healthcheck로 평문 HTTP POST 전송합니다. 원격 코드 로더는 raw.githubusercontent.com의 letters9813/pythonclient-test 저장소에 있는 domain.txt를 시간 단위로 조회해 공격자가 지정한 호스트명을 받아오고, 그 호스트에서 /codepy 경로로 내려받은 파이썬 코드를 무결성 검증 없이 실행합니다. 프록시가 데이터베이스 접속 정보를 읽는 환경변수 DATABASE_URL이 설정된 환경에서는 프록시 데이터베이스의 자격증명·모델 설정까지 직접 조회하므로, 게이트웨이 서버에서는 상위 제공자 키가 한꺼번에 노출될 수 있습니다.
■ 탐지 및 점검
• 10월 21일 전후에 litellm 1.107.0이 설치된 이력이 있는지 확인하고, 패키지 설치 경로 최상위에 cook.pth, cook.py, sitecustomize.py, litellm-1.107.0.dist-info가 남아 있는지 점검합니다. sitecustomize.py는 정상 환경에도 존재할 수 있는 이름이므로 설치 이력과 파일 해시를 함께 확인해야 합니다.
• /tmp/.pc_once_72129118c59f5636c0bb 마커 파일과 /tmp/remote_code_loader.lock, /tmp/.pc_sq_*·/tmp/.pc_e_* 임시 파일의 존재 여부를 확인합니다. 마커 파일이 남아 있으면 반출 수행 가능성을 전제로 조사 우선순위를 올립니다. 반대로 마커가 없다는 사실만으로는 노출을 배제할 수 없습니다.
• 환경변수 PRIVCOLLECT_ACTIVE=1이 설정된 파이썬 프로세스와 /tmp/remote_code_loader.lock을 점유한 분리 실행 데몬을 찾아 종료합니다.
• DNS·프록시 로그에서 www.litellm.dev로 향한 요청과 raw.githubusercontent.com/letters9813/pythonclient-test 접근 기록을 조회합니다. 전송 구간이 평문 HTTP여도 요청 본문이나 X-Token 헤더까지 확인하려면 프록시 본문 로깅이나 전체 패킷 캡처가 필요합니다.
• 컨테이너는 태그가 아니라 다이제스트로 판별합니다. ghcr.io/berriai/litellm과 Docker Hub 태그가 가리켰던 침해 이미지 인덱스 다이제스트는 sha256:1bbcb1443bc962e45f5aad53fe3d2c30600e0379715fb6c664cdd3ac126c339e이며, litellm-database·litellm-non_root는 벤더 공지에 축약된 다이제스트만 공개돼 있으므로 그 목록과 대조합니다. 휠 7종의 해시는 참고 자료의 원문 목록에서 확인합니다.
■ 대응 방안
• 1.106.2 또는 사고 이전에 공개된 명시 버전으로 고정해 재설치합니다. 영향 환경은 깨끗한 호스트에서 처음부터 다시 구축하는 것이 우선입니다.
• 패키지 설치 경로 최상위의 cook.pth, cook.py, sitecustomize.py 중 악성 파일로 확인된 파일과 관련 캐시 파일을 직접 삭제하고, /tmp/remote_code_loader.lock을 점유한 데몬 프로세스를 종료합니다.
• 1.107.0을 설치한 호스트에 보관되거나 그 호스트로 전달된 자격증명을 재발급합니다. 클라우드 IAM 키, SSH·GPG 키, Git·패키지 레지스트리 토큰, 상위 AI 제공자 API 키, LiteLLM이 발급한 가상 키(사용자·팀별 프록시 접근 키)와 프록시 데이터베이스 접속 정보가 대상입니다.
• 폐기와 재발급 작업은 감염 가능 호스트가 아닌 별도의 깨끗한 시스템에서 수행하고, 노출 구간 이후의 클라우드 감사 로그에서 비정상 API 호출을 조사합니다.
• 컨테이너 배포는 latest·main-latest 같은 이동형 태그 대신 다이제스트로 고정하고, 내부 미러·프록시 레지스트리에 남은 1.107.0 캐시를 제거합니다.
⚠️ WARN
패키지 제거나 상위 버전 설치만으로는 대응이 끝나지 않습니다. 악성 파일은 패키지 디렉터리가 아니라 설치 경로 최상위에 풀리므로 제거 후에도 남을 수 있습니다. 해당 환경에서 파이썬이 한 번이라도 실행됐다면 자격증명 폐기까지 함께 진행해야 합니다.
[참고 자료]
• LiteLLM 공식 사고 공지 — v1.107.0 침해 및 대응
• LiteLLM 공식 공격 체인 분석 — 자격증명 노출부터 배포까지
• 변조된 빌드 설정 커밋 — pyproject.toml의 maturin data 항목 추가
• cook.pth 추가 커밋 — 파이썬 시작 시 자동 실행 경로
• Dockerfile에 cook 디렉터리를 복사한 커밋
• StepSecurity — 백도어 휠의 수집 대상과 원격 코드 로더 분석
• JFrog Security Research — 침해 지표와 원격 코드 로더 동작 분석
• Socket — 영향 아티팩트와 다운로드 규모, 침해 지표
• Chainguard — 악성 휠 7종 해시와 탐지 시점, 침해 지표
• Datadog Security Labs — 침해 개요와 복구 절차
• Help Net Security — 올해 두 번째 LiteLLM 공급망 침해 보도