-
axios에 악성코드가 심어졌다 - 북한 해커의 npm 공급망 공격 분석IT 2026. 4. 7. 21:00
2026년 3월 31일, JavaScript 생태계에서 가장 많이 쓰이는 HTTP 클라이언트 라이브러리 axios가 해킹당했다. 주간 다운로드 8,300만~1억 회에 달하는 패키지에 원격 접근 트로이목마(RAT)가 심어진, 역대 최대 규모의 npm 공급망 공격이다.
axios가 뭔데?
axios는 JavaScript/TypeScript 진영의 사실상 표준(de facto standard) HTTP 클라이언트 라이브러리다. 브라우저의
XMLHttpRequest와 Node.js의http모듈을 하나의 Promise 기반 API로 추상화하여, 프론트엔드와 백엔드 어디서든 같은 코드로 HTTP 요청을 보낼 수 있게 해준다.왜 이렇게 많이 쓰이는 걸까?
- 브라우저 + Node.js 겸용: 브라우저에서는
fetch의 상위 호환, Node.js에서는node-fetch를 따로 설치할 필요 없이 하나로 통일된다 - 인터셉터(Interceptor): 요청/응답을 가로채서 인증 토큰 자동 삽입, 에러 핸들링, 로깅 등을 미들웨어 패턴으로 처리할 수 있다.
fetch에는 이런 기능이 없다 - 자동 JSON 변환: 응답을 자동으로 JSON 파싱하고, 요청 body도 자동 직렬화한다
- 타임아웃, 요청 취소, 진행률 추적:
fetch에서 직접 구현해야 하는 기능들이 내장되어 있다 - 생태계 관성: React, Vue, Angular 튜토리얼 대부분이 axios를 기본 HTTP 클라이언트로 사용한다. 2014년부터 쌓인 문서와 예제가 방대하다
Python의
requests, Go의net/http에 해당하는 위치라고 보면 된다. 주간 다운로드 8,300만~1억 회라는 숫자는 npm 전체에서도 최상위권이다. 그만큼 이 패키지 하나가 뚫리면 파급력이 어마어마하다는 뜻이기도 하다.무슨 일이 일어났나
2026년 3월 31일 00:21 UTC, axios의 npm 메인테이너 계정(jasonsaayman)이 탈취되어 두 개의 악성 버전이 발행되었다:
- axios@1.14.1 — 00:21 UTC 발행
- axios@0.30.4 — 01:00 UTC 발행
두 버전 모두 약 3시간 뒤인 03:29 UTC에 npm에서 제거되었다. StepSecurity가 최초 발견했고, 이후 Snyk, Huntress, Elastic Security Labs 등 다수 보안 업체가 분석 결과를 공개했다.
공격 메커니즘: postinstall hook + 가짜 의존성
공격 방식이 교과서적으로 정교했다.
- 가짜 의존성 주입: axios 코드에는 실제로 import하지 않는
plain-crypto-js@4.2.1이라는 패키지가 dependencies에 추가되었다 - postinstall hook 실행:
npm install만 하면 이 가짜 패키지의 postinstall 스크립트가 자동 실행된다 - RAT 다운로드: C2 서버(
sfrclak[.]com:8000)에서 플랫폼별(Windows, macOS, Linux) 원격 접근 트로이목마를 다운받아 실행한다
npm install axios한 줄이면 시스템이 뚫리는 구조다. CI/CD 파이프라인에서 자동으로npm install을 실행하는 환경이라면, 사람이 인지하기도 전에 빌드 서버가 감염될 수 있다.왜 두 버전인가
axios@1.14.1은 현재 최신 메이저 라인(1.x), axios@0.30.4는 레거시 라인(0.x)이다. 공격자는 두 라인 모두를 타겟했다. 최신 버전만 쓰는 프로젝트든, 레거시에 묶여있는 프로젝트든 가리지 않겠다는 전략이다.
^1.0.0이나^0.30.0같은 semver range를 쓰는 프로젝트라면npm install시 자동으로 악성 버전을 받게 된다.배후: 북한 해킹 그룹 UNC1069
Google Threat Intelligence Group(TIG)이 이번 공격을 UNC1069로 귀속했다. 북한 국가 지원 해킹 그룹으로, 암호화폐 탈취와 공급망 공격을 주로 수행하는 것으로 알려져 있다.
메인테이너 계정 탈취 경로는 GitHub Actions CI/CD를 우회하여 npm에 직접 발행하는 방식이었다. GitHub 저장소의 코드에는 악성코드 흔적이 없고, npm 레지스트리에만 올라간 버전에 악성 코드가 포함되어 있었다는 점이 특징이다.
내 서버 점검 결과
이 소식을 접하고 바로 내 DGX Spark 서버를 전수 점검했다. 홈 디렉토리 아래 모든 프로젝트를 검사한 결과:
프로젝트 axios 사용 버전 상태 Google Workspace CLI (Node.js 글로벌) O 1.13.5 안전 챗봇 게이트웨이 (Python) X (httpx) - 해당없음 미디어 관리 도구 (Python) X (requests) - 해당없음 RAG 검색 시스템 (Python) X - 해당없음 음성 처리 파이프라인 (Python) X - 해당없음 웹 대시보드 (정적 HTML) X - 해당없음 GPU 스케줄러 (Bash) X - 해당없음 LLM 추론 서버 (C++) X - 해당없음 결론: 안전. axios를 사용하는 곳은 @googleworkspace/cli 하나뿐이고, 설치된 버전은 1.13.5로 악성 버전(1.14.1, 0.30.4)이 아니다. Python 프로젝트들은 대부분
requests나httpx를 사용하고 있어 이번 공격의 영향권 밖이었다.감염 여부 확인 방법
본인 시스템을 점검하고 싶다면:
# 설치된 모든 axios 버전 찾기 find / -path "*/node_modules/axios/package.json" -exec grep '"version"' {} + 2>/dev/null # package-lock.json에서 악성 버전 검색 grep -r "axios.*1\.14\.1\|axios.*0\.30\.4" */package-lock.json # 가짜 의존성이 설치되었는지 확인 find / -path "*/node_modules/plain-crypto-js" 2>/dev/null만약 악성 버전이 설치된 흔적이 있다면, 즉시 다음을 수행해야 한다:
- 악성 버전 제거 후 안전한 버전으로 다운그레이드 (1.14.0 또는 0.30.3)
- npm 토큰, AWS/GCP/Azure 키, SSH 키 등 모든 크리덴셜 교체
- .env 파일에 노출된 시크릿 값 변경
- CI/CD 시크릿 로테이션
- 감염 시점 이후의 시스템 로그 분석
교훈: npm 생태계의 구조적 취약점
이번 사건이 시사하는 점:
- 단일 메인테이너 리스크: 주간 1억 다운로드 패키지의 npm 발행 권한이 개인 계정 하나에 묶여 있었다
- postinstall hook의 위험성:
npm install만으로 임의 코드가 실행될 수 있는 구조는 근본적으로 위험하다.--ignore-scripts옵션을 기본값으로 두는 것을 고려해볼 만하다 - npm과 GitHub의 분리: GitHub 코드에는 없고 npm 패키지에만 악성 코드가 있었다. 소스 코드 리뷰만으로는 잡을 수 없다
- semver range의 양면성:
^1.0.0같은 유연한 버전 지정은 편리하지만, 악성 패치 버전을 자동으로 끌어온다
lockfile(
package-lock.json)을 커밋하고, CI에서npm ci를 사용하며,npm audit을 정기적으로 돌리는 기본적인 수칙이 다시 한번 강조되는 사건이다.
이 글은 생성형 AI의 도움을 받아 작성되었습니다.
'IT' 카테고리의 다른 글
GitHub 오픈소스 PR 리뷰, 놓치지 않는 자동화 시스템 만들기 (0) 2026.04.12 AI 코딩 에이전트의 자기 진화 학습 시스템 — 실수를 기억하고 성장하는 에이전트 만들기 (1) 2026.04.11 Qdrant 벡터 DB, 임베디드 모드에서 Docker 서버로 전환한 이유 — 로컬 RAG 시스템 구축 삽질기 (0) 2026.04.10 캘린더 싱크의 중복 지옥, event_id로 탈출하기 — Google Calendar → Obsidian 자동화 삽질기 (1) 2026.04.09 Claude Code가 플랜을 짜는 방법 - Plan Mode 내부 동작 원리 (0) 2026.04.08 Claude Code Hooks로 AI 에이전트의 다단계 파이프라인을 결정적으로 만들기 (0) 2026.04.06 Qwen3.5-122B 양자화 비교: Q4_K_M vs Unsloth UD-Q3_K_XL 실측 (1) 2026.04.05 텔레그램 AI 어시스턴트에 기억을 심다 — 단기·에피소드·장기 메모리 설계기 (1) 2026.04.04 로컬 VLM으로 가족사진 3만 장 분석하기 — 열흘간의 대장정 (0) 2026.04.03 Context7 분석 (5) 다층 품질 스코어링 (1) 2026.04.02 - 브라우저 + Node.js 겸용: 브라우저에서는