# 샤이훌루드 재등장: 300개 이상 NPM 패키지 감염

> Clean Markdown view of GeekNews topic #24589. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=24589](https://news.hada.io/topic?id=24589)
- GeekNews Markdown: [https://news.hada.io/topic/24589.md](https://news.hada.io/topic/24589.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2025-11-25T09:37:25+09:00
- Updated: 2025-11-25T09:37:25+09:00
- Original source: [helixguard.ai](https://helixguard.ai/blog/malicious-sha1hulud-2025-11-24)
- Points: 17
- Comments: 5

## Summary

NPM 레지스트리에서 **1,000개 이상의 패키지**가 몇 시간 만에 감염되어, **Bun 런타임 설치 스크립트로 위장한 악성 코드**가 퍼지는 대규모 공급망 공격이 다시 발생했습니다. 이 코드는 **TruffleHog**을 이용해 개발 환경의 **AWS·GCP·GitHub·NPM 토큰**을 탈취하고, **GitHub Actions 러너(SHA1HULUD)** 를 통해 외부로 유출하며, `npm publish`를 자동 실행해 **웜 형태로 자기 복제**까지 수행했습니다. 결과적으로 **27,000개 이상의 GitHub 저장소**가 감염되며, 오픈소스 생태계 전반의 신뢰 체계가 다시 흔들리고 있습니다.

## Topic Body

- NPM 레지스트리에서 **1,000개 이상의 구성요소**가 몇 시간 만에 동일한 방식으로 감염되어 악성 코드가 포함된 새 버전이 배포됨  
- 악성 패키지는 **Bun 런타임 설치 스크립트**로 위장해 `setup_bun.js`와 난독화된 `bun_environment.js`를 추가, 실행 시 **TruffleHog**을 이용해 로컬 자격 증명 탈취  
- 수집된 **AWS/GCP/Azure·GitHub·NPM 토큰** 등 민감 정보는 `SHA1HULUD`라는 GitHub Action 러너를 통해 외부로 전송됨  
- 악성 스크립트는 `npm publish`를 자동 실행해 **웜 형태의 자기 복제**를 수행, 결과적으로 **27,000개 이상의 GitHub 저장소**가 감염됨  
- 오픈소스 생태계 전반에 걸친 **공급망 보안 위협**이 다시 부각된 사례로 평가됨  

---
### 공격 개요
- 2025년 11월 24일 HelixGuard는 NPM 레지스트리에서 **1,000개 이상의 패키지**가 몇 시간 내 동일한 수법으로 감염된 것을 탐지  
  - 새 버전들은 Bun 런타임을 추가하는 것처럼 위장하며 `preinstall: node setup_bun.js` 스크립트를 포함  
  - 함께 배포된 `bun_environment.js` 파일은 난독화된 악성 코드로, 실행 시 TruffleHog을 내려받아 실행함  
- TruffleHog은 로컬 환경에서 **NPM 토큰, AWS/GCP/Azure 자격 증명, 환경 변수** 등을 스캔해 탈취  
- 탈취된 정보는 GitHub Action 러너 `SHA1HULUD`를 생성하고, `Sha1-Hulud: The Second Coming.`이라는 설명을 가진 GitHub 저장소를 통해 외부로 유출  
- HelixGuard는 이 공격이 2025년 9월 발생한 **“Shai-Hulud” 사건**과 동일 공격자일 가능성을 시사함  

### 악성 코드 동작 분석
- 예시로 `@asyncapi/specs` 패키지를 분석한 결과, NPM에 배포된 버전은 감염되었으나 GitHub 원본 저장소는 안전함  
- 공격자는 `package.json`을 수정해 `setup_bun.js`를 추가하고, 해당 스크립트가 `bun_environment.js`를 호출하도록 구성  
- `bun_environment.js`는 10MB 이상 크기의 **고도 난독화된 자바스크립트 파일**로, 주요 기능은 다음과 같음  
  - 환경 변수에서 **클라우드 자격 증명 및 토큰 수집**  
  - TruffleHog을 이용한 비밀키 스캔  
  - GitHub Actions를 통한 데이터 유출  
- 또한 `package.json`을 수정해 감염 코드를 삽입하고, `npm publish`를 자동 실행하여 **웜 형태의 전파**를 수행  

### GitHub 감염 및 데이터 유출
- 악성 스크립트는 `.github/workflows/formatter_123456789.yml` 파일을 생성하고, `SHA1HULUD` 러너를 등록  
- 해당 워크플로는 저장소의 비밀키를 **이중 Base64 인코딩**한 `actionsSecrets.json` 파일로 패키징  
- 이후 `Sha1-Hulud: The Second Coming.` 설명을 가진 무작위 이름의 GitHub 저장소를 생성해 데이터를 업로드  
- HelixGuard는 **27,000개 이상의 GitHub 저장소**가 감염된 것으로 확인  
- 탈취된 비밀 정보에는 `AWS_ACCESS_KEY_ID`, `SLACK_WEBHOOK_URL`, `CODECOV_TOKEN`, `WEBFLOW_TOKEN` 등 다양한 서비스 자격 증명이 포함됨  

### 감염된 패키지 목록
- HelixGuard는 **수백 개의 NPM 패키지**가 감염된 것으로 보고  
  - 대표적으로 `@asyncapi`, `@ensdomains`, `@posthog`, `@zapier`, `@postman`, `@voiceflow` 등 주요 조직의 패키지가 포함  
  - 각 패키지는 다수의 버전(예: `@asyncapi/specs@6.8.2`, `@postman/csv-parse@4.0.5`)이 감염됨  
- 감염된 패키지들은 대부분 정상적인 오픈소스 프로젝트를 위장하고 있으며, **자동 배포 과정에서 악성 코드가 삽입된 형태**  

### 보안적 시사점
- 이번 공격은 **공급망 보안의 취약점**을 악용해 대규모 오픈소스 생태계를 감염시킨 사례  
- NPM·GitHub·클라우드 자격 증명 등 **개발 인프라 전반의 보안 관리 강화 필요성**이 드러남  
- HelixGuard는 감염된 패키지의 설치를 즉시 중단하고, 관련 토큰 및 자격 증명을 **즉시 폐기할 것**을 권고함

## Comments



### Comment 46840

- Author: ahwjdekf
- Created: 2025-11-27T02:44:29+09:00
- Points: 1

js 생태계는 난장판 스레기가 정말 맞습니다

### Comment 46781

- Author: zihado
- Created: 2025-11-25T18:21:15+09:00
- Points: 1

https://github.com/search?q=Sha1-Hulud%3A+The+Second+Coming.&type=repositories&s=updated&o=asc

### Comment 46768

- Author: developerjhp
- Created: 2025-11-25T14:11:10+09:00
- Points: 1

실시간 스캐너 스크립트를 만들어보았어요.  
  
의심되는 리포지토리의 path에서   
npx sha1-hulud-scanner  
  입력하시면됩니다.  
  
소스코드 : https://github.com/developerjhp/sha1-hulud-scanner

### Comment 46745

- Author: neo
- Created: 2025-11-25T09:37:25+09:00
- Points: 2

###### [Hacker News 의견](https://news.ycombinator.com/item?id=46032539) 
- 팁 하나 공유함: **NPM 대신 PNPM**을 쓰는 게 좋음  
  PNPM 10.x는 여러 공격 벡터를 차단함  
  1️⃣ 기본적으로 post-install 스크립트를 실행하지 않으며, 수동 승인 필요함  
  2️⃣ 새 릴리스가 배포된 후 일정 기간(예: 4일) 지나야 설치되도록 설정 가능함  
  NPM은 프로덕션 CLI 환경에서 너무 **불안정**함  
  퍼블리셔 키는 최소 권한으로 제한하고, 특정 패키지에만 바인딩하며, IP를 CI/CD 러너에 묶는 게 좋음  
  로컬에 퍼블리시 키를 두지 말고, 필요하면 OIDC Trusted Publisher나 토큰 기반 접근을 고려함
  - NPM은 **기술 부채**가 너무 쌓인 결과물 같음  
    락파일만 해도 다섯 번은 시도했는데, 여전히 완벽하지 않음  
    구조와 커밋 히스토리를 보면 팀이 열심히 개선 중이지만, 너무 깊은 **구덩이**에서 시작한 느낌임  
    여전히 파일 전송 중 조기 EOF를 감지 못하고, 캐시에 불완전한 파일을 남겨서 느린 인터넷 환경에서는 업데이트 실패로 시간 낭비가 심함
  - 나는 **HashiCorp Vault / OpenBao**의 동적 비밀 관리 방식을 선호함  
    처음엔 복잡하지만, 비밀을 **임대(lease)** 개념으로 관리할 수 있음  
    CI 빌드마다 임대를 생성하고 종료 시 자동 폐기되며, TTL과 자동 회전도 지원함  
    덕분에 장기 자격 증명을 숨기고, 빌드 시점에만 짧은 수명의 토큰을 발급할 수 있음  
    이런 공격 덕분에 회사 내에서 진짜 **보안 논의**가 활발해지는 건 긍정적임
  - 단순히 `npm ci`를 쓰면 됨  
    package-lock.json에 명시된 버전만 설치하므로 자동 업데이트로 인한 공격 위험을 줄일 수 있음  
    **의도적 업데이트**만 수행하는 습관이 중요함
  - Python 생태계에서는 `pip install --only-binary=:all:` 옵션으로 비슷한 보호를 얻을 수 있음  
    소스 배포를 완전히 차단하고 **wheel**만 설치함  
    다만 버전 제약이 생길 수 있음  
    `uv`에서는 `--exclude-newer` 옵션으로 PNPM의 ‘최소 릴리스 기간’ 기능을 흉내낼 수 있음
  - 최근 “**dependency cooldown**” 관련 글을 봤는데, 매우 공감됨  
    나는 모든 의존성을 고정하고 dependabot 알림을 수동으로 검토함  
    이게 과한 건지, 올바른 습관인지는 아직 고민 중임

- 오늘 특히 관련 있는 글이 있음: [“We should all be using dependency cooldowns”](https://blog.yossarian.net/2025/11/21/We-should-all-be-using-dependency-cooldowns)  
  자동 의존성 업데이트는 하루짜리 취약점보다 더 위험할 수 있음  
  이미 수천 개의 lock 파일에 퍼진 **감염된 패키지**를 되돌리는 게 훨씬 어려움
  - 아예 필요할 때만 업데이트하는 게 낫다고 생각함  
    잘 작동한다면 굳이 건드릴 이유가 없음
  - 하지만 그렇게 해도 다른 사람이 버그를 잡아줘야 하고, 모두가 쿨다운을 쓰면 결국 제자리걸음일 수 있음
  - Python의 `uv`에서는 `uv lock --exclude-newer $(date --iso -d "24 hours ago")` 명령으로 비슷한 효과를 낼 수 있음  
    관련 논의는 [이슈 #14992](https://github.com/astral-sh/uv/issues/14992)에 있음
  - npm-check-updates로도 간단히 가능함  
    `npx npm-check-updates -c 7` 명령으로 7일 쿨다운 설정 가능함  
    [npm-check-updates 문서](https://www.npmjs.com/package/npm-check-updates#cooldown) 참고
  - 이 논리에 동의하지 않음  
    쿨다운은 0-day 취약점 확산 시간을 늘릴 수 있음  
    모두가 같은 쿨다운을 쓰면 **발견 지연**만 생길 뿐임

- **PostHog 공동 창업자**임  
  이번 공격의 피해자였음  
  감염된 버전은 posthog-node 4.18.1, 5.13.3, 5.11.3 / posthog-js 1.297.3 / posthog-react-native 4.11.1 / posthog-docusaurus 2.0.6  
  키와 비밀번호를 모두 교체하고, 새 버전을 배포했음  
  원인 분석 중이며 [status.posthog.com](https://status.posthog.com)에 업데이트 예정임
  - 새 패키지 릴리스가 CI/CD 실행과 연관되지 않으면 **알람**이 울리도록 설정하길 권장함
  - 감염된 JS가 실제 사용자에게 영향을 줬는지 궁금함  
    웹사이트가 감염된 버전을 배포했다면, 방문자에게 피해가 있었는지 알고 싶음
  - 원인을 모른다면 공격이 여전히 **확산 중**일 가능성도 있음
  - 최신 버전이 또 감염될 수도 있는데, 왜 사람들이 이번엔 믿어야 하는지 의문임
  - 트위터 공지보다 여기 업데이트가 더 눈에 잘 띄어 다행임. 복구 잘 되길 바람

- 진지한 질문임: **Node로 새 프로젝트를 시작하는 게 맞는가**  
  Astro로 SaaS 프론트엔드를 만들고 있는데, 의존성 업데이트할 때마다 불안함  
  npm 생태계의 **보안 부재**가 너무 심각하게 느껴짐
  - 문제는 Node나 JS가 아니라 **패키징 모델**임  
    Rust처럼 수많은 서브패키지에 의존하는 생태계도 언젠가 같은 일을 겪을 것임  
    C, C++, Odin처럼 패키지 매니저가 없는 게 오히려 보안상 현명한 선택일 수도 있음
  - 나는 Node보다는 **npm 자체의 문제**라고 생각함  
    최근엔 Deno의 [JSR](https://jsr.io/)을 더 신뢰함  
    JSR 기반 패키지는 npm에도 교차 배포되고, Deno 전용 패키지들도 있음  
    예를 들어 [Lume](https://lume.land/)은 느리지만 안정적인 SSG로 인상 깊었음
  - Node만의 문제가 아님  
    npm이 가장 큰 저장소라 공격자 입장에서 **가치가 높을 뿐**임  
    RubyGems나 Cargo에서도 충분히 일어날 수 있음
  - Node를 피하자는 의견은 과함  
    단지 가장 많이 쓰이는 생태계라 공격이 집중되는 것뿐임  
    의존성을 신중히 관리하고, 매일 업데이트하지 않으면 됨
  - 우리는 제품 보안 분석 플랫폼을 **PHP**로 개발했음  
    페이지 렌더링에 100개 넘는 의존성이 필요하지 않다는 점이 장점임  
    [프로젝트 링크](https://github.com/tirrenotechnologies/tirreno) 참고

- 요즘은 모든 개발을 **Podman 컨테이너** 안에서만 함  
  읽지 않은 코드는 반드시 격리된 환경에서 실행함  
  완벽하진 않지만, 최소한의 **보안 습관**이라 생각함
  - 대부분의 사람들은 99.99%의 경우 문제가 없으니 위험 감각이 둔함  
    보안은 보통 **전문가에게 위임**되는 영역이라, 현실적으로 바꾸기 어려움
  - npm 패키지는 의존 트리가 너무 깊은데, 이런 경우 컨테이너 격리가 어떻게 작동하는지 궁금함
  - PostHog SDK 같은 npm 패키지를 컨테이너 안에서 어떻게 다루는지 구체적인 방법이 궁금함
  - Docker보다 Podman이 더 안전하고, 필요하면 QEMU 같은 추가 격리도 고려할 만함
  - 나는 아예 다른 로컬 사용자로 SSH 접속해 tmux로 개발함

- 12년 전 NPM이 한 번 완전히 **다운**된 적이 있었음  
  그때는 단순한 오픈소스 프로젝트였지만, 지금은 **Microsoft** 소유임  
  세계 최대 기업 중 하나라면 이런 문제를 해결해야 하지 않겠음?  
  하지만 여전히 별로 달라진 게 없음
  - MS는 **Windows조차 제대로 관리하지 못함**  
    엔터프라이즈 라이선스로 돈이 안 되는 건 방치함  
    그래서 Windows 11은 마케팅 덩어리 같음

- 우리는 현재 공격 활동을 **모니터링 중**이며, 감염된 패키지 목록을 [Wiz 블로그](https://www.wiz.io/blog/shai-hulud-2-0-ongoing-supply-chain-attack)에 업데이트하고 있음  
  악성 페이로드를 리버스 엔지니어링 중이며, 몇 시간 내 결과를 공유할 예정임

- PostHog의 “Talk to a human” 채팅이 실제로는 **로봇 응답**이라 불편했음  
  긴급 지원 링크도 제대로 안내되지 않음  
  그래서 묻고 싶음 — 어떤 버전을 피해야 함?
  - 공동 창업자임. 메인 스레드와 [status.posthog.com](https://status.posthog.com)에 이미 공지했음  
    감염된 버전은 posthog-node 4.18.1, 5.13.3, 5.11.3 / posthog-js 1.297.3 / posthog-react-native 4.11.1 / posthog-docusaurus 2.0.6  
    최신 버전으로 업데이트하면 안전함
  - Slack 채널에서도 같은 버전 목록을 공유받았음

- 왜 항상 **Node 생태계**에서 이런 패키지 혼란이 생기는지 궁금함  
  왜 이 커뮤니티는 복잡한 설치 훅과 자동 업데이트를 좋은 엔지니어링이라 믿는지 모르겠음  
  Node 창시자가 이미 떠난 이유가 이해됨
  - Node는 새로운 **PHP** 같음  
    거대한 생태계, 초보 개발자 중심, 보안 의식 부족, 그리고 작은 기능도 라이브러리에 의존함
  - 진지한 생태계라면 **패키지 메인테이너**가 존재해야 함  
    Debian처럼 신뢰할 수 있는 관리자가 검증해야 하는데, JS 커뮤니티는 이를 **게이트키핑**이라며 거부함  
    그래서 이런 사태가 반복됨
  - 남을 깎아내려 우월감을 느끼는 건 잠시뿐임  
    그런 태도로는 아무것도 바뀌지 않음

- 약간 주제에서 벗어나지만, **HelixGuard**가 누구인지 궁금함  
  웹사이트는 엉망이고, 정보도 거의 없음  
  고객이 암호화폐 거래소라는데 뭔가 수상함
  - X(트위터) 계정에 따르면 싱가포르/일본 기반임  
    [HelixGuard X 계정](https://x.com/HelixGuard_ai)

### Comment 46773

- Author: laeyoung
- Created: 2025-11-25T15:15:42+09:00
- Points: 2
- Parent comment: 46745
- Depth: 1

2️⃣ 새 릴리스가 배포된 후 일정 기간(예: 4일) 지나야 설치되도록 설정 가능함  
----  
너무 좋은 기능이네요. 구글도 종종 버그에 작동 안하는 버전 NPM에 올릴 때 있어서 내 버근가 하고 당황 할 때가 있는데.
