빌드·배포 시스템 어딘가가 침해된 것으로 보임. BerriAI/litellm의 공개 커밋에는 data = "cook"이나 cook/ 폴더가 전혀 없음.
SafeDep은 중간~높은 수준의 확신으로, BerriAI의 비공개 릴리스 파이프라인이 공격자가 수정한 Git 소스로 이 wheel 패키지들을 빌드했다고 평가함.
에이전트 실행 도구들은 지금 “우리가 이런 일을 하려면 굳이 시스템을 침해할 필요도 없겠네”라고 생각할 법함.
sandbox-exec와 Lulu 규칙을 아무리 써도 이런 공격은 막지 못함. 어느 순간 권한 승인 팝업에 지쳐 아무 권한이나 당연하게 허용하게 됨. brew나 npm으로 도구를 설치하는 일에도 무감각해짐.
“패키지 X가 도구 367개를 설치한다고? 요즘은 다 그런가 보네.” “Brew에서 패키지 59개가 오래됐다고? 업데이트해야지. 완료했으니 됐네.” 이런 식임.
에이전트와 실행 도구까지 등장했으니, 이제 사고가 날지가 아니라 언제 날지가 관건임. 운영체제 차원의 격리가 필요함. 더 쉽고 가벼운 VM이라도 제공해 사용자가 완전히 분리된 프로그램 실행 공간을 손쉽게 만들 수 있어야 함. 물론 Unix와 Linux는 알렉산드로스 대왕이 기저귀를 차기도 전에 전부 해결했다는 소리가 나올 것도 알고 있음.
무슨 소리인가? 의존성 설치를 24시간 유예하는 것만으로도 이런 침해에서 사용자를 보호하기에 충분함. 이번 공격은 새로운 기법도 아니었고, 새로 등록한 유사 도메인을 명령·제어 서버로 쓰고 이미 알려진 PTH 기법을 활용했을 뿐임.
샌드박스는 알려지지 않은 공격에 대비하는 수단이며, 프로파일을 제대로 설정하기가 까다롭다는 점은 맞음.
오히려 Linux 셸이 승인 피로를 먼저 만든 것 아닌가? 우리도 업그레이드나 설치·설정이 그냥 진행되도록 미리 -y 옵션을 붙이곤 했음. 에이전트가 더 자주, 더 장황한 팝업을 띄울 뿐 새로운 현상은 아님. VM도 만능 해결책은 아님.
누군가 릴리스에 파일을 어떻게 몰래 집어넣었는지 이해가 안 됨. 빌드 파일에서 디렉터리를 만든다는 내용만 보이고, 새 파일이나 의존성 추가가 어떻게 통과했는지는 보이지 않음. cook.pth가 설치 시 PyPI에서 자동으로 내려받는 의존성이었고, 빌드 시스템이 이를 의존성에 넣었다는 뜻인가?
나중에 확인한 내용을 남겨둠. 비공개 릴리스 파이프라인이 공격자가 수정한 Git 소스로 wheel을 빌드했다고 함. 탈취한 관리자·봇 자격 증명, 비공개 브랜치나 미러, 파이프라인이 빌드 대상으로 삼는 참조가 이용됐을 수 있음. 공격자가 자기 컴퓨터에서 훔친 PyPI 토큰을 사용했다는 가설은 증거와 덜 부합함.
그렇다면 이해가 됨. 모두가 받는 의존성 자체를 탈취한 것이 아니라, 관리자나 비공개 파이프라인을 공격해 관리자의 로컬 사본에 악성 의존성을 주입한 셈임. 상당히 교묘함.
그렇다면 출처 증명(attestation) 도 이번에는 막아주지 못했을 것임. 어떤 워크플로가 wheel을 배포했는지는 증명하지만, 그 워크플로가 어떤 소스를 체크아웃했는지는 증명하지 못함. 겉보기에 같은 저장소를 비공개 파이프라인에서 빌드해도 유효한 증명을 얻을 수 있음.
잡아내려면 공개 태그로 다시 빌드해 결과를 비교해야 하는데, Python wheel에 대해 그렇게 하는 사람은 거의 없음. 나도 내 프로젝트 릴리스에서는 출처 증명이 해답이라고 여겼는데, 그 한계를 다시 깨닫게 됨.
uv, npm 등은 기본적으로 24~48시간 설치 유예 기간을 두고, 그보다 새 패키지를 설치하려면 사용자가 별도 조치를 해야 한다고 봄.
사내 PyPI 프록시에서 7일 유예를 적용하고 있지만, 보안 업데이트까지 막혀서 지금은 수동으로 예외 처리해야 함. 이를 제대로 자동화할 방법은 잘 모르겠고, LLM부터 시도하는 게 최선일 수도 있음.
마지막으로 찾아봤을 때 공급망 공격의 발견까지 걸리는 기간 중앙값이 수개월에서 수년이라는 자료를 본 기억이 남. 그보다 짧은 유예 기간은 효과 없는 처방처럼 보임.
그러면 악성코드 발견도 24~48시간 늦어지는 것 아닌가?
도구들에 이미 그런 기능이 추가된 줄 몰랐음. 지난해 이런 공격이 처음 시작됐을 때 우리 프로젝트에도 적용했는데, 보편화되고 있다니 반가움.
관건은 기본 유예 기간이 끝나기 전에 공격을 찾아 격리할 보안 연구자가 충분한지임.
어떤 경우에는 너무 빨리 업데이트하는 것보다 배포 파이프라인의 빌드에 의존성 버전을 고정하지 않는 것이 더 큰 원인 아닐까?
지난번 사고 때 LiteLLM 대체 구현을 바이브 코딩으로 만들었는데, 실제로 더 잘 작동함.
지난 공급망 공격을 겪었으면 이제는 LiteLLM을 넣은 제품을 배포하지 않을 정도의 판단은 할 줄 알았음.
이번에는 첫 공격 이후에도 LiteLLM에서 옮겨가지 않은 사람만 피해를 본다는 점이 눈에 띔. 취약점이 한 번 생겼다고 무조건 옮기라는 건 아니라고 하고 싶지만, 사실상 그렇게 말하고 싶음. 프로그래밍 언어처럼 거대하고 기반이 되는 기술이 아니라면 몇 주 안에 옮기는 편이 나음. PHP 정도는 두 번째 기회를 줄 수 있음.
나는 첫 사고 때도 설치하지 않았으니, 이상적인 개발자, 즉 여러분의 경쟁자는 이 의존성으로 인한 피해를 한 번도 겪지 않았음. 한 번 당한 것도 좋지 않지만, 두 번 당했다면 정신을 차릴 계기로 삼아야 함. 같은 의존성에 세 번 당하면 가망이 없음.
https://github.com/BerriAI/litellm/issues/47826#issuecomment...
OSS 사용자는 당분간 1.106.2 또는 현재 시점 이전에 배포된 특정 버전으로 고정해야 함.
기업 고객용으로는 비공개 LiteLLM 레지스트리가 있으며, 10월 27일 공개 예정인 취약점을 수정한 공개 유예 릴리스를 이곳에서 배포하고 있음. 비공개 레지스트리는 영향을 받지 않았으므로, 여기서 패키지를 받는 기업 고객은 이번 공격의 영향을 받지 않음.
그러면 다른 사람의 LiteLLM 인스턴스를 해킹할 수 있는 정보에 대한 선행 접근권을 파는 셈 아닌가? 좀 비윤리적으로 보임.
또 LiteLLM이라니, 관리자를 신뢰할 수 있는지 의문이 듦.
LiteLLM에 또 이런 일이 생긴 건가? Google ADK 같은 도구가 이걸 내 의존성에 추가하지 않았으면 좋겠음.
널리 쓰이고 무료이며 접근 제한이 없는 소프트웨어는 결국 모두 오염될 것임. 오픈소스 세계의 케슬러 증후군 같은 셈임.