패키지가 손상되었습니다. 실제로 배포한 버전을 어떻게 증명하나요?
Source: Dev.to
Background
지난 주에 LiteLLM의 배포 파이프라인이 침해되었습니다. 공격자는 CI/CD 시스템에 있는 취약점 스캐너를 장악하고, PyPI 자격 증명을 탈취한 뒤, 악성 버전을 푸시해 이를 설치한 모든 엔지니어의 API 키를 유출했습니다. 3일 뒤, 같은 일이 Telnyx에서도 발생했습니다.
AI와 작업한다면 아마 LiteLLM을 설치했을 것입니다. 진짜 질문은 여러분이 영향을 받았는지가 아니라, 어떤 버전을 언제 실행했는지 증명할 수 있느냐는 점입니다.
공급망 공격은 새로운 것이 아닙니다 (SolarWinds, Codecov, ua‑parser‑js). 패턴은 언제나 동일합니다: 개발자와 사용자 사이의 무언가가 침해됩니다. 새로워진 것은 대응 문제입니다.
LiteLLM이 공격을 받았을 때, 이를 사용하고 있던 모든 팀은 “우리는 침해된 버전을 실행하고 있었는가?” 라는 질문에 답해야 했습니다. 대부분은 확신을 가지고 답하지 못했습니다. 왜냐하면 증거가 침해되었을 가능성이 있는 동일한 시스템에서 나오기 때문입니다. CI 로그는 CI에, 레지스트리 타임스탬프는 레지스트리에서, 내부 기록은 내부에서 나오며, 논쟁 중인 시스템 자체가 증거의 출처이기 때문에 이는 증명으로서 충분하지 않습니다.
앵커링을 해결책으로
앵커링은 아티팩트(패키지, 모델, 빌드)의 암호학적 지문을 생성하고 이를 비트코인 블록체인에 타임스탬프합니다. 이는 복사본이나 백업이 아니라 정확히 그 순간에 그 아티팩트가 존재했다는 수학적 증명입니다.
artifact.whl (your package)
↓ SHA‑256
a7c3f9e… (fingerprint)
↓ anchor
origin_id: ec8eead9‑… (your proof)
↓ Bitcoin
anchored to Bitcoin block 889,412
이 증명은 독립적으로 검증 가능하며 CI 제공자, 레지스트리, 혹은 단일 시스템이 정직하게 유지된다는 것에 의존하지 않습니다.
How to anchor
CLI (one line)
umarise anchor dist/package-1.2.0.whl
GitHub Actions
- name: Anchor build artifact
uses: AnchoringTrust/anchor-action@v1
with:
file: dist/package-1.2.0.whl
env:
UMARISE_API_KEY: ${{ secrets.UMARISE_API_KEY }}
Python SDK
import hashlib
from umarise import UmariseCore
with open("dist/package-1.2.0.whl", "rb") as f:
sha256 = "sha256:" + hashlib.sha256(f.read()).hexdigest()
client = UmariseCore(api_key="um_...")
result = client.attest(hash_value=sha256)
print(result.origin_id)
그게 전부입니다—한 번 호출하면 증명이 영구적으로 저장됩니다.
LiteLLM 공격 타임라인 (앵커링 유무 비교)
| Day | Event | Without anchoring | With anchoring |
|---|---|---|---|
| 0 | 팀이 litellm 1.52.6 (정식 버전) 을 배포 | 버전이 PyPI에 존재 | SHA‑256 지문을 비트코인에 앵커링 |
| 3 | 공격자가 CI 스캐너를 장악하고 PyPI 자격 증명을 추출, litellm 1.52.7 을 푸시 | – | – |
| 4 | 악성 버전이 .env 파일에서 API 키를 탈취 (1000명 이상의 엔지니어 영향) | – | – |
| 6 | 공격이 발견되어 버전이 회수됨 | – | – |
| 7 | 사고 대응 시작 | “우리 로그에는 1.52.6이 있었다”고 주장 | “우리가 실행하고 있던 정확한 버전을 비트코인에 앵커링한 증거가 여기 있다” |
차이는 명확합니다: 주장 vs. 누구든지 독립적으로 영원히 검증할 수 있는 증명.
왜 중요한가
- 버전 출처: 지난 화요일에 배포한 의존성 버전을 증명할 수 있나요?
- CI 침해에 대한 복원력: CI 제공자가 침해당하면 증거가 유지될까요?
- 규제 준수: 규제 기관이 프로덕션에 무엇이 있었는지 증명을 요구한다면, 자체 시스템이 아닌 무언가를 제공할 수 있나요?
대부분의 팀은 세 가지 모두에 “아니오”라고 답합니다.
LiteLLM 사건은 파이썬 패키지를 목표로 했지만, 파이프라인을 통과하는 모든 아티팩트에도 동일한 취약점이 존재합니다:
- ML 모델: 의사결정이 이루어졌을 때 프로덕션에 있던 가중치를 증명합니다.
- 학습 데이터: 감사 후 데이터셋이 수정되지 않았음을 증명합니다.
- Docker 이미지: 프로덕션에서 실행된 이미지가 빌드된 이미지와 일치함을 증명합니다.
- 펌웨어: 배포된 바이너리가 서명된 바이너리임을 증명합니다.
독립적인 증거가 없는 모든 아티팩트는 동일한 유형의 공격에 취약합니다.
시작하기
pip install umarise
umarise anchor
발행 파이프라인에 시간적 증명을 추가하는 것은 단 한 줄이면 됩니다. 앵커링하기 전에는 “Our logs say so.”가 있습니다. 앵커링한 후에는 “Verify it yourself.”가 됩니다.
Links
- Umarise CLI & SDK – 터미널이나 CI에서 앵커링
- GitHub Action – 모든 워크플로에서 원스텝 앵커링
- Anchoring Specification – 오픈 표준, 18개 섹션
- Case study: Supply chain integrity – 전체 LiteLLM 타임라인
- Integration examples – MLflow, W&B, HuggingFace, S3