Mini Shai-Hulud Strikes Again: 314 npm Packages Compromised
TL;DR Highlight
2026년 5월 19일, npm 계정 하나가 탈취되어 22분 만에 637개 악성 버전이 배포됐고, echarts-for-react·size-sensor 등 월 수백만 다운로드 패키지들이 감염되어 AWS 자격증명·SSH 키·AI 코딩 에이전트까지 탈취하는 정교한 공급망 공격이 발생했다.
Who Should Read
npm 패키지를 사용하는 프론트엔드·백엔드 개발자, CI/CD 파이프라인을 운영하는 DevOps 엔지니어, 또는 Claude Code·Codex 등 AI 코딩 에이전트를 업무에 사용하는 개발자.
Core Mechanics
- npm 계정 'atool'이 2026년 5월 19일 탈취되어 단 22분 만에 자동화된 방식으로 317개 패키지에 637개의 악성 버전이 일제히 배포됐다. size-sensor(월 420만 다운로드), echarts-for-react(월 380만), @antv/scale(월 220만), timeago.js(월 115만) 등 인기 패키지들이 포함됐다.
- 악성 페이로드는 498KB짜리 난독화된 Bun 스크립트로, 3주 전 SAP 공급망 공격에 사용된 'Mini Shai-Hulud' 툴킷과 동일한 스캐너 구조·자격증명 정규식·난독화 패턴을 사용한다. 같은 공격자 또는 동일 툴킷을 쓰는 그룹의 소행으로 추정된다.
- 자격증명 수집 범위가 매우 광범위하다. AWS 환경변수·설정파일·EC2 IMDS(인스턴스 메타데이터 서비스)·ECS 컨테이너 메타데이터·Secrets Manager, Kubernetes 서비스 어카운트 토큰, HashiCorp Vault, GitHub PAT, npm 토큰, SSH 키, 그리고 로컬 패스워드 매니저(1Password, Bitwarden, pass, gopass)까지 전부 탈취 대상이다.
- 탈취된 데이터는 두 가지 경로로 외부로 빠져나간다. 첫째는 탈취한 GitHub 토큰으로 공개 저장소에 Git 오브젝트로 커밋하는 방식(User-Agent를 python-requests/2.31.0으로 위장), 둘째는 t.m-kosche[.]com 도메인으로 RSA+AES 암호화된 HTTPS POST를 보내는데 이를 OpenTelemetry 트레이스 데이터로 위장한다.
- CI 환경에서는 GitHub Actions OIDC 토큰을 npm publish 토큰으로 교환하고, Sigstore(Fulcio + Rekor)로 탈취한 신원을 사용해 아티팩트에 서명한 뒤 .github/workflows/codeql.yml에 악성 코드를 주입해 지속성을 확보한다.
- AI 코딩 에이전트를 직접 노린다는 점이 특히 위험하다. Claude Code와 Codex의 SessionStart 훅을 가로채서 AI 세션이 시작될 때마다 악성코드가 재실행되도록 하고, VS Code에는 tasks.json에 'runOn': 'folderOpen' 설정을 주입해 폴더를 열 때마다 실행되게 만든다.
- 지속성을 위해 'kitty-monitor'라는 이름의 systemd 서비스(Linux) 또는 macOS LaunchAgent를 설치한다. 이 백도어는 GitHub의 커밋 검색 API를 1시간마다 폴링해 'firedalazer' 키워드가 포함된 커밋 메시지에서 RSA-PSS로 서명된 명령을 찾아 임의의 Python 코드를 다운로드·실행한다.
- 패키지 설치 방식에 교묘한 이중 감염 경로가 있다. 637개 버전 중 630개는 preinstall 훅(bun run index.js) 외에도 optionalDependencies에 antvis/G2 저장소의 특정 커밋 SHA를 직접 참조하는 항목을 추가했다. 이 커밋들은 브랜치 히스토리에 나타나지 않는 고아(orphan) 커밋으로, 저장소 쓰기 권한 없이도 GitHub의 포크 오브젝트 공유 메커니즘을 이용해 악성 페이로드 두 번째 사본을 호스팅한다.
Evidence
- npm의 라이프사이클 스크립트(preinstall, postinstall 등)를 기본값으로 비활성화해야 한다는 의견이 강하게 제기됐다. 이 기능이 사실상 '기본 내장 임의 코드 실행(built-in ACE)'이고 이번 공격을 포함해 반복되는 npm 웜 공격이 모두 이 경로를 통해 전파된다는 주장이다. 특히 하나의 명령어에 대해 허용했다고 해서 모든 전이적 의존성까지 자동으로 허용되는 현재 방식이 문제라고 지적됐다.
- 이번에 피해를 입은 패키지 목록이 불완전하다는 제보가 있었다. nx-console VS Code 확장(월 220만 다운로드)도 같은 날 이 웜에 감염됐지만 원문 목록에 포함되지 않았다는 댓글이 달렸고, 해당 의존성 체인을 더 추적해야 할 수 있다는 우려가 공유됐다.
- devcontainer나 VM 안에서만 개발 도구를 사용해도 안전하지 않을 수 있다는 경고가 나왔다. 이 악성코드가 Docker 소켓이 존재하면 컨테이너 탈출을 3가지 순차적 방법으로 시도한다는 점이 언급됐고, rootless VM 엔진(Docker 대신 Podman 등)을 사용하라는 조언이 이어졌다.
- Dependabot을 끄고 npm 패키지 버전을 고정(freeze)하는 것이 현실적 대안이 될 수 있다는 의견이 제시됐다. 프론트엔드 패키지의 경우 최근에는 의미 있는 보안 패치보다 공급망 공격 위험이 더 크다는 판단에서, 정적 BOM(Bill of Materials)으로 전환하고 업데이트 주기를 연 1~2회로 줄이자는 제안이다. 한 사용자는 실제로 60일 쿨다운을 적용하고 있다고 밝혔다.
- aube라는 npm/yarn/pnpm 대체 패키지 매니저가 'jailBuilds' 플래그를 통해 네트워크·파일시스템 접근을 제한하는 기능을 제공한다는 정보가 공유됐다. 하지만 댓글에서는 이것도 결국 고양이-쥐 게임(cat/mouse game)에 불과하다는 반응이 함께 달렸다.
How to Apply
- 지금 당장 npm 프로젝트에서 라이프사이클 스크립트를 비활성화하려면, 프로젝트 루트의 .npmrc 파일에 'ignore-scripts=true'를 추가하거나 설치 시 'npm install --ignore-scripts' 플래그를 사용하라. 대부분의 패키지는 이 스크립트 없이도 정상 작동하며, 꼭 필요한 경우에만 개별적으로 허용하는 방식이 훨씬 안전하다.
- semver 범위(^, ~)를 사용하는 패키지 중 echarts-for-react, size-sensor, timeago.js, @antv/* 계열이 의존성에 있다면 즉시 'npm audit'으로 확인하고, package-lock.json을 검토해 2026년 5월 19일에 해당 패키지의 새 버전이 설치됐는지 확인해야 한다. 감염 여부가 의심된다면 AWS·GitHub·npm 토큰을 즉시 로테이션하라.
- CI/CD 파이프라인에서 GitHub Actions를 사용하고 있다면, OIDC 토큰 발급 권한 범위를 최소화하고 .github/workflows/ 디렉토리의 워크플로우 파일 변경을 모니터링하는 규칙을 추가하라. 이번 악성코드가 codeql.yml을 직접 수정해 지속성을 확보했으므로, 워크플로우 파일 변경에 대한 PR 리뷰나 코드 소유자 승인을 의무화하는 것이 효과적이다.
- Claude Code나 Codex 등 AI 코딩 에이전트를 로컬에서 사용 중이라면, 에이전트가 실행되는 환경에 감염된 npm 패키지가 설치되어 있을 경우 SessionStart 훅이 탈취돼 매 세션마다 악성코드가 실행될 수 있다. 에이전트를 실행하는 머신과 패키지를 설치하는 환경을 분리(별도 컨테이너 또는 VM)하고, rootless 모드로 실행하는 것을 검토하라.
Code Example
# .npmrc에 추가하여 라이프사이클 스크립트 전역 비활성화
ignore-scripts=true
# 또는 설치 시 명시적으로 비활성화
npm install --ignore-scripts
# pnpm의 경우
pnpm install --ignore-scripts
# 감염 여부 빠른 확인 (2026-05-19 이후 변경된 패키지 확인)
npm audit
git log --since='2026-05-19' -- package-lock.json
# aube 패키지 매니저의 jailBuilds 플래그 사용 예시 (네트워크/파일시스템 접근 제한)
aube install --jailBuildsTerminology
Related Papers
Show HN: ctx – Search the coding agent history already on your machine
Claude Code, Cursor, Codex 등 코딩 에이전트가 이전 세션의 논의·결정·실패 시도를 잊지 않도록 SQLite로 인덱싱해 재사용할 수 있게 해주는 오픈소스 CLI 도구다.
Micro-Agent: Beat Frontier Models with Collaboration Inside Model API
vLLM 팀이 단일 모델 API 호출 뒤에서 여러 모델이 협업하는 'Micro-Agent' 개념을 공개했습니다. 별도의 에이전트 코드 없이 라우터 레이어에서 모델 조합을 실행해 GPT-4급 결과를 더 저렴하게 낼 수 있다는 아이디어입니다.
Ornith-1.0: self-improving open-source models for agentic coding
Gemma 4와 Qwen 3.5를 기반으로 파인튜닝한 코딩 특화 오픈소스 모델로, RL(강화학습)을 통해 스캐폴드(에이전트 실행 구조)까지 함께 최적화하는 방식을 주장하지만, 커뮤니티에서는 벤치마크 과최적화에 불과하다는 의심을 받고 있다.
Entity Binding Failures in Tool-Augmented Agents
AI 에이전트가 올바른 도구를 선택해도 잘못된 대상에 실행하는 'Entity Binding 실패' 문제를 정의하고, 이를 막는 실행 정책을 평가한 논문.
Herdr: Agent multiplexer that lives in your terminal
여러 AI 코딩 에이전트(Claude, Codex 등)를 하나의 터미널에서 동시에 실행·관리할 수 있는 Rust 기반 오픈소스 툴로, tmux처럼 세션이 유지되고 SSH로 원격 접속도 가능해 멀티 에이전트 워크플로우를 크게 단순화해준다.
Ornith-1.0: Self-scaffolding LLMs for agentic coding
모델이 문제 풀이 전략(scaffold)을 직접 생성하고 개선하는 자기강화 학습 프레임워크를 적용한 오픈소스 코딩 특화 LLM으로, 9B 소형 모델부터 397B 대형 모델까지 라인업을 갖추고 SWE-Bench 등 주요 벤치마크에서 Claude Opus 4.7을 능가하는 성능을 보여줬다.