axios 사례로 본 npm 공급망 공격의 메커니즘

2026-05-15 hit count image

2026년 3월 npm 생태계를 강타한 axios 공급망 공격 사례를 분석합니다. 메인테이너 계정 탈취, 악성 의존성 주입, postinstall 스크립트를 통한 RAT 배포까지의 공격 흐름과 npm 신뢰 모델의 구조적 취약점을 다룹니다.

web

들어가며

2026년 3월 31일, 주간 다운로드 1억 회 이상을 기록하는 HTTP 클라이언트 라이브러리 axios가 공급망 공격(supply chain attack)을 받았습니다. 사고는 약 4시간 만에 봉합되었지만, 그 짧은 시간 동안 전 세계 수많은 프로젝트가 잠재적 위험에 노출되었습니다.

이 글은 3부작 시리즈의 첫 번째 글로, axios 공격 사례를 통해 npm 공급망 공격이 어떻게 작동하는지 그 메커니즘을 분석합니다. 이어지는 두 번째 글에서는 실제로 적용한 방어 전략과 구현 디테일을, 세 번째 글에서는 방어 전략의 유효성과 한계를 다룹니다.

공급망 공격이란

공급망 공격이란 소프트웨어가 의존하는 외부 구성 요소(라이브러리, 빌드 도구, 배포 파이프라인 등)를 통해 최종 사용자에게 악성 코드를 전달하는 공격 방식을 말합니다. 직접 타깃을 공격하는 대신, 타깃이 신뢰하고 사용하는 무언가를 먼저 침해함으로써 그 신뢰의 사슬을 타고 침투합니다.

대표적인 형태는 다음과 같습니다.

  • 패키지 레지스트리 공격: npm, PyPI, RubyGems 등 공개 레지스트리의 정상 패키지를 침해
  • 빌드 시스템 공격: CI/CD 파이프라인이나 빌드 도구 자체를 침해 (SolarWinds, 3CX 사례)
  • 메인테이너 행위: 메인테이너 본인이 의도적으로 악성 코드를 삽입 (colors.js, node-ipc 사례)
  • 장기 침투: 신뢰 관계를 수년에 걸쳐 구축한 뒤 백도어 삽입 (XZ Utils 사례)

이번 글에서 다루는 axios 사례는 이 중 패키지 레지스트리 공격, 그중에서도 메인테이너 계정 탈취형 공격에 해당합니다.

axios 공격 사례

개요

항목내용
발생 시점2026년 3월 31일 00:38 UTC 무렵
영향 패키지axios, plain-crypto-js
악성 버전[email protected], [email protected]
안전 버전[email protected], [email protected]
봉합 시간약 4시간 이내
주간 다운로드1억 회 이상

사고 흐름

공격자는 axios의 리드 메인테이너인 jasonsaayman의 계정을 탈취한 뒤, 계정의 이메일을 자신의 주소([email protected])로 변경했습니다. 이후 통상의 CI/CD 파이프라인을 우회하고 npm CLI를 통해 직접 악성 버전을 약 39분 안에 두 개의 릴리즈 브랜치(1.x, 0.x)에 게시했습니다.

정상적인 axios 릴리즈는 GitHub Actions와 npm OIDC Trusted Publisher를 사용하여 암호학적 서명을 남기지만, 이번 악성 버전에는 그 서명이 없었습니다. 이것이 이번 사고의 결정적 포렌식 단서가 되었습니다.

탐지 자체는 매우 빨랐습니다. npm 공급망 보안 SaaS인 Socket이 AI 기반 패키지 행동 분석으로 게시 후 6분 만에 이상을 포착했고, GitHub Actions 런타임 보안 SaaS인 StepSecurity가 곧이어 경보를 발령했습니다. 하지만 그 사이 약 4시간 동안 자동 업데이트나 신규 설치를 통해 악성 버전을 받아간 사례가 존재할 수 있습니다.

공격 메커니즘 분석

이번 공격이 정교했던 이유는 단순히 한 패키지를 변조한 것이 아니라, 2단계 구조로 페이로드를 분리했다는 점입니다.

1단계: 신규 의존성 주입

공격자는 먼저 [email protected]이라는 새로운 패키지를 npm 레지스트리에 게시했습니다. 이 패키지의 유일한 목적은 postinstall 스크립트를 실행하는 것이었습니다.

그리고 침해된 axios 버전에 이 패키지를 신규 의존성으로 추가했습니다. 패치 노트만 보면 평범한 의존성 변경처럼 보이지만, 실제로는 모든 axios 설치자가 자기도 모르는 사이에 악성 페이로드를 함께 다운로드하도록 만든 것입니다.

[email protected]
└── [email protected]   ← 악성 (postinstall만을 위해 존재)

2단계: postinstall 스크립트 실행

plain-crypto-jspostinstall 훅은 다음과 같은 동작을 합니다.

  • 런타임에 디코딩되는 난독화된 페이로드 임베드
  • 동적 모듈 로딩으로 정적 분석 회피
  • sfrclak.com(IP: 142.11.206.73)과 C2 통신
  • OS별로 다른 경로에 RAT(Remote Access Trojan) 드롭
OS페이로드 배치 경로
macOS/Library/Caches/com.apple.act.mond
Windows%PROGRAMDATA%\wt.exe
Linux/tmp/ld.py

즉, yarn install 또는 npm install을 실행한 순간 — 코드를 실행하기도 전에 — 개발자의 PC나 CI 서버는 이미 백도어가 심긴 상태가 됩니다.

왜 이 공격이 위험한가

영향 범위가 광대하다

axios는 React, Vue, Node.js 백엔드 등 자바스크립트 생태계 전반에서 사용되는 사실상의 표준 HTTP 클라이언트입니다. 직접 의존하지 않더라도 다른 라이브러리가 의존하기 때문에 간접 의존(transitive dependency) 으로 들어와 있는 경우가 압도적으로 많습니다.

yarn install을 한 번 실행했을 때 받아오는 수백~수천 개의 패키지 중 단 하나라도 이런 식으로 침해되면, 그 즉시 영향권에 들어갑니다.

postinstall이 사일런트 실행 트리거가 된다

postinstall은 본래 네이티브 모듈 빌드 등 정당한 용도로 사용되는 npm 훅이지만, 개발자의 명시적 허락 없이 임의의 코드를 실행할 수 있다는 특성 때문에 공급망 공격의 가장 매력적인 진입점이 됩니다.

특히 위험한 환경은 다음과 같습니다.

  • 개발자 PC: 브라우저 세션, SSH 키, 클라우드 자격증명 등 고가치 자산이 모여 있음
  • CI 환경: 배포용 토큰, 시크릿이 환경 변수로 노출됨
  • 프로덕션 빌드 서버: 빌드 산출물에 악성 코드를 주입할 수 있는 위치

탐지가 빠르더라도 노출은 막을 수 없다

이번 사고에서 Socket AI는 6분 만에 탐지했고 4시간 안에 패키지가 내려갔습니다. 매우 빠른 대응이지만, 자동 업데이트가 도는 환경에서는 이 시간 안에 이미 설치가 끝났을 가능성이 충분히 있습니다.

Dependabot이나 Renovate 같은 자동 PR 봇이 새 버전을 즉시 감지해 PR을 열고, CI가 그 PR의 의존성을 자동으로 설치한다면 — 사람이 머지하지 않더라도 — postinstall은 이미 CI 환경에서 실행됩니다.

npm 신뢰 모델의 구조적 한계

axios 공격은 일회성 사건이 아니라 구조적 문제의 발현입니다. npm 생태계의 신뢰 모델은 본질적으로 다음 가정 위에 서 있습니다.

  1. 메인테이너 계정은 안전하게 관리된다
  2. 메인테이너는 악의가 없다
  3. 새 버전은 검증된 상태로 게시된다

이 가정 중 하나라도 깨지면 — 그리고 실제로 모두 깨진 사례들이 있습니다 — 자동 업데이트는 그 자체로 공격 벡터가 됩니다.

가정깨진 사례
메인테이너 계정 안전axios (2026), ua-parser-js (2021), event-stream (2018)
메인테이너의 선의colors.js (2022), node-ipc (2022)
새 버전의 무결성tj-actions/changed-files (2025) — GitHub Actions 태그 변조

npm은 기본적으로 메인테이너를 신뢰하고, semver 범위(^, ~)는 신뢰를 미래의 버전에까지 자동 확장하도록 설계되어 있습니다. 이 자동 확장이 공격 표면을 만들어내는 것입니다.

우리에게 시사하는 점

axios 공격에서 얻을 수 있는 교훈은 다음과 같습니다.

1. “유명한 패키지니까 안전하다”는 무너졌다

다운로드 수가 많을수록 표적이 되기 쉽다는 역설이 성립합니다. 인기 패키지일수록 공격자에게는 더 큰 보상이 되기 때문입니다.

2. 자동 업데이트는 양날의 검이다

보안 패치를 빠르게 받기 위한 자동 업데이트가, 동시에 공급망 공격을 가장 빠르게 받아들이는 통로가 됩니다.

3. postinstall은 의심해야 한다

설치 시점에 실행되는 스크립트는 본질적으로 RCE(Remote Code Execution)와 같습니다. 기본적으로 비활성화하는 방향이 안전합니다.

4. 시간이 가장 강력한 필터다

악성 패키지는 거의 항상 수 시간에서 수 일 안에 적발되어 내려갑니다. 즉, 새 버전이 나오자마자 받지 않는 것 자체가 강력한 방어가 됩니다. 이 부분은 시리즈의 3편에서 데이터와 함께 다룹니다.

마무리

axios 사례는 “유명하고 잘 관리되는 패키지조차 4시간 동안 무방비 상태가 될 수 있다”는 사실을 보여줍니다. 이 사실을 받아들이고 나면 다음 질문이 따라옵니다.

우리는 무엇을 할 수 있는가?

다음 글 공급망 방어 전략 및 구현에서는, 이번 공격을 계기로 실제 프로젝트에 적용한 세 가지 방어 전략 — GitHub Actions의 SHA 핀닝, Dependabot cooldown, Yarn의 npmMinimalAgeGate — 을 코드 레벨에서 자세히 다룹니다.

제 블로그가 도움이 되셨나요? 하단의 댓글을 달아주시면 저에게 큰 힘이 됩니다!

앱 홍보

책 홍보

블로그를 운영하면서 좋은 기회가 생겨 책을 출판하게 되었습니다.

아래 링크를 통해 제가 쓴 책을 구매하실 수 있습니다.
많은 분들에게 도움이 되면 좋겠네요.



SHARE
Twitter Facebook RSS