기술당신은 타인을 얼마나 믿을 수 있는가? : 공급망 공격

김주형
2026-04-22
조회수 155

54e2abdadc481.png


Max의 금요일 저녁: npm install이 더 이상 안전한 명령어가 아닌 이유

b7cbcaa8e4774.png개발자 Max는 마감을 앞둔 금요일 저녁, Slack 메시지를 한 통 받았다. 업계에서 이름을 들어봤을 만한 스타트업 창업자의 초대였다.
문체는 자연스러웠다.

링크를 따라 들어간 워크스페이스는 이상할 정도로 자연스러웠다. 수십 명의 팀원 프로필, 몇 달 치 쌓여 있는 채팅 로그, 외부 플랫폼에서 교차 검증되는 인물들까지.
며칠 뒤 열린 Microsoft Teams 미팅에는 여러 명의 얼굴이 화면에 동시에 떠 있었다.

그런데, 그 무대 위에서 실존하는 인물은 Max 한 사람뿐이었다.

스타트업 자체가 가짜였다. 워크스페이스도, 팀원도, 영상 속 얼굴들도 — 전부 이 한 번의 침투를 위해 설계된 무대 장치였다.

다음 주 월요일 새벽, Max가 관리하던 npm 패키지에 새 버전이 올라갔다. Max가 올린 게 아니었다.
그리고 몇 시간 뒤, 전 세계 약 60만 대의 개발자·운영 서버가 그 새 버전을 조용히 설치했다.



이건 가상의 이야기가 아니다. 2026년 3월 31일에 실제로 벌어진 Axios npm 공급망 공격의 흐름이다.


지난 8개월, npm은 몇 번이나 뚫렸나

Axios 사태는 갑자기 튀어나온 사건이 아니다. 2025년 중반부터 npm 생태계는 이미 여러 번 얻어맞고 있었다. 

cdff64606d241.png


  • 2025년 8월 — Nx 패키지 침해
    배포 권한이 탈취돼 약 4시간 동안 악성 버전이 공식 저장소에 올라갔다. 개발자 PC의 비밀키·환경설정 파일이 외부로 유출됐다.

  • 2025년 9월 8일 — chalk·debug 사건
    주간 합계 약 20억 번 설치되는 유명 패키지 18개가 한꺼번에 뚫렸다. 공격자는 암호화폐 지갑 주소를 몰래 바꿔치기하는 코드를 심었다.

  • 2025년 9월 16일 — Shai-Hulud 웜
    npm 역사상 최초의 자가 확산형 악성코드가 등장했다.
    개발자 계정 하나가 뚫리면, 그 계정이 관리하던 패키지 전부가 자동 감염되고, 다시 그 패키지를 쓰는 다른 개발자 계정으로 옮겨가는 구조였다.

  • 2025년 11월 — Shai-Hulud 2.0
    같은 계열 웜의 2차 공격. 약 800개 패키지, 월간 누적 1억 3천만 설치 규모가 영향을 받았다.

1년이 채 안 되는 사이, npm 생태계는 통째로 공격 사정권에 들어왔다.


그래서, Axios 사태는 어떻게 벌어졌나

Axios는 전 세계 자바스크립트 개발자가 가장 많이 쓰는 HTTP 통신 라이브러리 중 하나다. 

주간 1억 건 이상 설치된다. 

이 규모의 패키지는 단 한 번의 오염으로 수많은 서비스가 동시에 영향을 받는다.


[공격 단계]
  1. 사회공학기법 - 며칠에 걸친 신뢰 구축
    공격자는 Axios 관리자(Jason Saayman)를 표적으로 잡고, 실제 존재하는 기업 창업자를 사칭했다.
    Slack 워크스페이스 초대 → 가짜 팀 프로필 공개 → Microsoft Teams 화상 미팅으로 이어지는 다단계 낚시였다.
    Google Threat Intelligence Group(GTIG)은 이 방식이 북한 연계 위협 그룹 UNC1069의 기존 수법과 일치한다고 공식 귀속했다.

  2.  배포 권한 탈취
    신뢰가 쌓인 뒤, 공격자는 개발 환경을 장악할 수 있는 명령 실행을 유도했다.
    이 과정에서 만료 기한이 없는 npm 배포용 토큰이 공격자 손에 들어갔다.
    Axios 저장소의 식 사후 보고서(Issue #10636)에 관리자가 직접 작성한 유입 경로가 공개돼 있다.

  3. 악성 버전 배포
    2026년 3월 31일 UTC 00:21, 공격자는 훔친 토큰으로 axios@1.14.1을 공식 저장소에 올렸다.
    약 40분 뒤 axios@0.30.4도 올라갔다. 두 버전 모두 plain-crypto-js라는 가짜 의존성을 자동으로 끌어오도록 설계돼 있었다.

  4. 감염 시작
    plain-crypto-js에는 설치가 끝나면 자동 실행되는 스크립트가 포함돼 있었다.
    사용자가 따로 조작하지 않아도 npm install이 끝나는 순간 스크립트가 지정된 서버(sfrclak[.]com)에 접속해 OS별 원격 제어 악성코드를 내려받았다.
    여기서 특이한 건, 해당 악성코드가 설치된 환경(Windows · macOS · Linux)에 맞게 동작하는 구조로 만들어졌다는 점이다.
[피해 규모]  

Elastic Security LabsSANS Institute의 공식 분석을 종합하면 다음과 같다.

  • 악성 버전이 살아있던 시간: 약 3시간 (UTC 00:21 ~ 03:15)
  • 이 3시간 사이 설치된 것으로 추정되는 건수: 약 60만 건 (SANS Institute 추정)
  • 영향 받은 OS: Windows · macOS · Linux 전부
  • 최종 페이로드: WAVESHAPER.V2 — 북한 연계 APT UNC1069의 신형 원격 제어 악성코드 (Google GTIG 공식 귀속)

공급망 공격이 노리는 공통 경로

이전에 발생한 공격들을 모두 겹쳐 보면, 공격자가 걷는 길은 거의 비슷하다.

  • 사람을 뚫는다.
    코드가 아니라 개발자 계정을 사회공학으로 노린다. 피싱, 사칭, Slack·Teams까지 동원한다.

  • 자동 실행 지점을 악용한다.
    npm 패키지 설치 과정에는 사용자 개입 없이 자동 실행되는 스크립트 구간이 있다.
    여기에 악성코드를 심으면 피해자가 아무 버튼도 누르지 않아도 공격이 완료된다.

  • 연쇄로 퍼진다.
    한 패키지가 뚫리면 그걸 의존성으로 끌어다 쓰는 수많은 서비스가 동시에 감염된다.

공격 지점이 기업 방화벽 안쪽이 아니라, 기업이 이미 신뢰하고 있는 바깥쪽 공급자라는 게 핵심이다.
이미 신뢰된 출처에서 정상 경로로 내려온 코드이기 때문에 엔드포인트 보안 솔루션으로도 잘 잡히지 않는다.


당장 적용할 수 있는 방어는 무엇인가

지난 사건들 대부분이 2시간에서 12시간 사이에 악성 버전이 제거됐다.
즉, 신규 릴리스를 조금만 지연 설치해도 상당수 공격을 피할 수 있다는 뜻이다.

  1. 의존성 버전 고정(Pinning)
    package.json에서 ^, ~ 기호를 제거하고 정확한 버전으로 못 박는다.
    빌드 서버에서는 npm install 대신 npm ci 사용.

  2.  설치 시점 자동 실행 스크립트 차단
    --ignore-scripts 옵션을 기본값으로 두는 것만으로 자동 실행 기반 공격군 전체가 차단된다.

  3. 배포 출처 검증 요구
    메이저 패키지의 새 버전에 OIDC/SLSA 기반 빌드 출처 메타데이터가 없으면 자동 경고.
    Axios 악성 버전을 조기에 식별한 결정적 단서가 바로 이 메타데이터의 부재였다.

  4. 장기 유효 토큰 전수 감사
    npm 배포 토큰, GitHub Personal Access Token을 모두 점검하고 단기 토큰·빌드 시 자동 발급 방식으로 전환한다.
    GitHub도 2026년 6월부터 주간 100만 이상 다운로드 패키지에 단기 토큰을 의무화할 예정이다.

마무리 - 그리고 다음 질문

Axios 사태에서 가장 섬뜩한 건 악성코드 자체가 아니다.
관리자를 뚫기 위해 공격자가 며칠에 걸쳐 Slack 워크스페이스 전체를 위장하고, 가짜 팀 프로필을 깔아두고, 가짜 Teams 미팅까지 열었다는 사실이다.

이런 정교한 사회공학은, 솔직히 말해 사람이 손으로 일일이 설계하기엔 공이 너무 많이 든다.
실제로 Unit 42는 2025년 11월 Shai-Hulud 2.0 캠페인 분석에서, 공격 스크립트에 LLM이 생성한 것으로 추정되는 흔적(특정 주석 패턴 등)이 있음을 확인했다고 발표했다.

공격자는 이미 AI를 쓰고 있다. 그렇다면 방어자는 지금 어디쯤 와 있는가.

AI 기반 스피어피싱, 자동화된 사회공학, 그리고 그 격차에 대해서는 — 다음 글에서 이어가려 한다.


그 사이, 한 가지만 기억하자.

 
당신이 npm install을 입력하는 순간, 당신은 전 세계 수만 명의 낯선 개발자를 암묵적으로 신뢰하게 된다. 


1c7f9bacfa3de.png

[김주형] | [kjh@cela.kr]

카카오톡 채널 채팅하기 버튼