메뉴
HN
Hacker News • 53일 전

'샤이훌루드' 공급망 웜 공격으로 수억 건 패키지 감염

IMP
10/10
핵심 요약

주간 1억 회 이상 다운로드되는 Node.js 패키지인 keyv 및 관련 캐싱 라이브러리들의 유지보수자 GitHub 계정이 해킹당해 악성 코드가 주입되었습니다. 이 악성 코드는 사용자의 환경에 있는 npm, GitHub, AWS 등의 인증 정보를 탈취한 뒤 암호화하여 외부로 유출하며, 다른 유지보수자의 패키지로 자가 전파되는 웜(Worm) 형태로 작동합니다. 현재 수백 개의 패키지가 추가 감염되었으며 월 20억 건 이상의 설치에 영향을 미친 매우 심각한 공급망(Supply Chain) 보안 사고입니다.

번역된 본문

블로그 취약점 및 위협 Keyv와 관련 패키지들이 진행 중인 샤이훌루드(Shai-Hulud) 공급망(Supply chain) 공격으로 침해당해 작성자: Ilyas Makari | 게시일: 2026년 8월 4일

2026년 8월 4일, 공격자들은 주간 약 1억 2천만 회의 npm 다운로드를 기록하는 키-값(Key-value) 스토리지 라이브러리인 keyv 개발자의 GitHub 계정을 해킹했습니다. 그리고 이 권한을 이용해 패키지 전체에 자격 증명(credential)을 탈취하는 웜(Worm)을 주입했습니다. 동일한 개발자는 cacheable(월 2,900만 다운로드), flat-cache(월 5억 6,500만 다운로드), file-entry-cache(월 5억 5,700만 다운로드)를 포함한 널리 사용되는 여러 캐싱 유틸리티를 소유하고 있었으며, 이 모든 패키지가 동일한 공격에 휘말렸습니다.

이번 해킹은 메인 브랜치(main branch)에 악성 파일을 직접 푸시한 직후 새로운 릴리스를 즉시 발행하는 방식으로 이루어졌습니다. 즉, 악성 버전들이 GitHub Actions에 의해 서명된 유효한 출처(provenance)와 함께 npm에 게시되었습니다.

침해당한 패키지는 다음과 같습니다:

  • keyv 6.0.0 (월 6억 400만)
  • flat-cache 6.1.24 (월 5억 8천만)
  • file-entry-cache 11.1.6 (월 5억 7천 100만)
  • cacheable-request 13.0.20 (월 1억 3천 700만)
  • cacheable 2.5.1 (월 3천만)
  • @cacheable/memory 2.2.1 (월 2천 800만)
  • cache-manager 7.2.10 (월 1천 600만)
  • @cacheable/node-cache 3.1.2 (월 600만)
  • @cacheable/utils 2.5.1 (월 3천 400만)
  • @cacheable/net 2.1.1 (월 3,700)
  • ecto 5.0.1 (월 4,500)

또한, 이 공급망 웜이 주요 기업을 포함한 다른 유지보수자와 패키지로 매우 활발하게 확산되고 있습니다:

  • @deliveroo/reevent 1.0.1
  • @or-sdk/invitations 1.4.9
  • @picsart/ai-sdk 3.32.2
  • @qlik/embed-runtime 1.6.4
  • picasso.js 2.11.6

업데이트 (2026년 8월 4일, 13:37 CEST): 현재까지 최소 868개의 패키지(1,381개 버전)가 이 웜에 의해 감염되었으며, 글을 작성하는 시점 기준으로 이 패키지들의 월간 설치 횟수는 총 20억 회를 넘는 것으로 집계되었습니다.

발생 과정 패밀리에 포함된 모든 패키지는 두 개의 새로운 파일(setup.mjs와 Math_Symbol.js)을 받았으며, 각 package.json에는 "preinstall": "node setup.mjs" 항목이 추가되었습니다. 영향을 받는 버전에 대해 npm install을 실행한 사용자는 설치가 완료되기 전에 setup.mjs가 자동으로 실행되었을 것입니다.

setup.mjs는 강력하게 난독화된 드로퍼(dropper)입니다. 이 스크립트의 유일한 역할은 github[.]com/oven-sh/bun/...에서 Bun JavaScript 런타임을 조용히 다운로드하고, 이를 사용하여 실제 페이로드인 Math_Symbol.js를 실행하는 것입니다.

Math_Symbol.js는 강력하게 난독화된 728KB 크기의 JavaScript 파일입니다. 여기에는 희생자의 환경에서 비밀 정보를 수집하고, 수집한 데이터를 암호화한 뒤, "Shai-Hulud: Here We Go Again(샤이훌루드: 또 시작이다)"라는 설명이 적힌 공개 GitHub 저장소로 유출(exfiltrate)하는 자격 증명 탈쇠기(credential stealers)가 포함되어 있습니다. 또한 이 페이로드는 감염된 패키지 중 하나를 설치한 다른 유지보수자의 패키지를 감염시키는 웜 형태의 자가 전파 기능도 포함하고 있습니다.

탈취 대상 Math_Symbol.js 파일은 희생자 머신의 다양한 보안 저장소를 표적으로 하는 일련의 자격 증명 추출기를 구현합니다.

  • npm 토큰: ~/.npmrc를 읽고 파일 시스템을 스캔하여 다른 모든 .npmrc 파일을 찾습니다. authToken 값과 //registry.*:_authToken=... 항목을 추출합니다. 유출 전에 registry.npmjs[.]org/-/whoami에 대해 각 토큰을 실시간으로 검증합니다.
  • GitHub 토큰: 세 가지 토큰 형식이 표적입니다. 클래식 PAT(g hp_...), OAuth 토큰(gho_...), GitHub App 서버 간 토큰(ghs_...), 그리고 JWT OIDC 토큰입니다. 출처로는 ~/.config/gh/hosts.yml, 환경 변수, 그리고 파일 시스템 스캔이 포함됩니다. GitHub Actions 러너(runner)에서는 페이로드가 셸 명령을 실행하여 러너 프로세스 메모리를 직접 읽음으로써 전체 비밀 저장소를 덤프합니다. npm 게시에 사용되는 OIDC 토큰을 훔치기 위해 ACTIONS_ID_TOKEN_REQUEST_TOKEN 및 ACTIONS_ID_TOKEN_REQUEST_URL을 읽습니다.
  • AWS 자격 증명: 모든 명명된 프로파일을 파싱하는 ~/.aws/credentials 및 ~/.aws/config를 읽습니다. 그리고 AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN 환경 변수를 탈취합니다.
  • EC2 인스턴스 메타데이터 서비스(IMDS).
원문 보기
원문 보기 (영어)
Blog Vulnerabilities & Threats Keyv and friends compromised in active Shai-Hulud supply chain attack Keyv and friends compromised in active Shai-Hulud supply chain attack Written by Ilyas Makari Published on: Aug 4, 2026 On August 4, 2026, attackers compromised the GitHub account of the maintainer behind keyv , a key-value storage library with roughly 127 million weekly npm downloads, and used that access to inject a credential-stealing worm across the entire package family. The same maintainer owns cacheable (29M downloads/month), flat-cache (565M downloads/month), file-entry-cache (557M downloads/month), and several other widely-used caching utilities, all of which were swept up in the same attack. The compromise was carried out by pushing malicious files directly to the main branch and then immediately cutting a new release, meaning the poisoned versions were published to npm with valid provenance signed by GitHub Actions. The compromised packages include: keyv 6.0.0 (604M/month) flat-cache 6.1.24 (580M/month) file-entry-cache 11.1.6 (571M/month) cacheable-request 13.0.20 (137M/month) cacheable 2.5.1 (30M/month) @cacheable/memory 2.2.1 (28M/month) cache-manager 7.2.10 (16M/month) @cacheable/node-cache 3.1.2 (6M/month) @cacheable/utils 2.5.1 (34M/month) @cacheable/net 2.1.1 (3.7K/month) ecto 5.0.1 (4.5K/month) We are also also seeing very active community spread of this supply chain worm to other maintainers and packages, including major organizations: @deliveroo/reevent 1.0.1 @or-sdk/invitations 1.4.9 @picsart/ai-sdk 3.32.2 @qlik/embed-runtime 1.6.4 picasso.js 2.11.6 Update — August 4, 2026, 13:37 CEST: At least 868 packages (across 1381 versions) have been compromised by the worm, with a combined total of over 2 billion monthly installs at the time of writing. What happened Every package in the family received two new files, setup.mjs and Math_Symbol.js , along with a "preinstall": "node setup.mjs" entry added to each package.json . Anyone who ran npm install against an affected version would have had setup.mjs execute automatically before their install completed. setup.mjs is a heavily obfuscated dropper. Its only job is to silently download the Bun JavaScript runtime from github[.]com/oven-sh/bun/releases/download/bun-v1.3.13/ and use it to execute the real payload, Math_Symbol.js : execFileSync (<bun binary>, [&#x27;<script_dir>/ Math_Symbol .js&#x27;], { stdio: &#x27;inherit&#x27;, cwd: <script_dir> }) The Math_Symbol.js is a heavily obfuscated 728 KB JavaScript file containing credential stealers that harvest secrets from the victim&#x27;s environment, encrypt the findings, and exfiltrate them to a public GitHub repository whose description reads " Shai-Hulud: Here We Go Again ". The payload also contains worm-like propagation functionality to infect packages of other maintainers that have installed one of the compromised packages. What it steals The Math_Symbol.js file implements a set of credential extractors, each targeting a different secret store on the victim machine. npm tokens Reads ~/.npmrc and scans the filesystem for any other .npmrc files. Extracts authToken values and any //registry.*:_authToken=... entries. Validates each token live against registry.npmjs[.]org/-/whoami before exfiltrating. GitHub tokens Three token formats are targeted: classic PATs ( ghp_... ) and OAuth tokens ( gho_... ), GitHub App server-to-server tokens ( ghs_... ), and JWT OIDC tokens. Sources include ~/.config/gh/hosts.yml , environment variables, and a filesystem scan. On GitHub Actions runners, the payload also executes a shell command that reads the runner process memory directly to dump the entire secret store. It reads ACTIONS_ID_TOKEN_REQUEST_TOKEN and ACTIONS_ID_TOKEN_REQUEST_URL to steal OIDC tokens used for npm publishing. AWS credentials ~/.aws/credentials and ~/.aws/config , parsing all named profiles AWS_ACCESS_KEY_ID , AWS_SECRET_ACCESS_KEY , and AWS_SESSION_TOKEN environment variables EC2 Instance Metadata Service at 169.254.169.254 , trying IMDSv2 first with a fallback to IMDSv1 ECS container metadata endpoint at 169.254.170.2 AWS Secrets Manager, calling secretsmanager:ListSecrets across multiple regions to enumerate and exfiltrate all secrets stored there Kubernetes secrets Reads the service account token, CA certificate, and namespace from /var/run/secrets/kubernetes.io/serviceaccount/ . Uses the service account token to query the Kubernetes API directly and retrieve all secrets in the namespace. Also targets KUBECONFIG and ~/.kube/config . HashiCorp Vault tokens Checks six sources in priority order: the VAULT_TOKEN environment variable, ~/.vault-token , the GitHub Actions runner path /home/runner/.vault-token , several well-known container paths, a Kubernetes auth login using the stolen service account JWT, and Vault&#x27;s AWS IAM auth endpoint using any stolen AWS credentials. After obtaining a token, it enumerates all KV stores via /v1/sys/mounts and reads every secret from KV v1 and v2 paths. Stripe and Slack tokens Scans for Stripe API keys (both test and live, sk_ and pk_ prefixes) and Slack tokens ( xox[baprs]-... ) across all files touched by the filesystem scanner. Generic filesystem scan A platform-aware scanner (macOS vs Linux) runs roughly 200 glob patterns across the filesystem, targeting among other things: .env , .env.* , and .envrc files Private key files ( *.pem , *.key , *.p12 , *.pfx , *.jks ) SSH keys and config ( id_rsa , id_ed25519 , .ssh/config ) Terraform state files and .tfvars Docker registry credential files ( docker/config.json ) KeePass databases ( *.kdbx ) VPN configs ( *.ovpn ) IDE config files including .vscode/tasks.json and .claude/settings.json Files over 5 MB are skipped. Up to 64 concurrent reads are used. A generic regex engine is also applied across all scanned files, flagging PEM private keys, SSH public keys, Azure storage keys, database connection strings with embedded credentials, and generic key=value patterns matching common secret field names. How Aikido detects this If you are an Aikido user, check your central feed and filter on malware issues. This will surface as a 100/100 critical issue. Aikido rescans nightly, but we recommend triggering a manual rescan now. If you are not yet an Aikido user, you can create an account and connect your repos. Our malware coverage is included in the free plan, no credit card required. For broader coverage across your whole team, Aikido&#x27;s Device Protection gives you visibility and control over the software packages installed on your team&#x27;s devices. It covers browser extensions, code libraries, IDE plugins, and build dependencies, all in one place. Stop malware before it gets installed. For future protection, consider Aikido Safe Chain (open source). Safe Chain sits in your existing workflow, intercepting npm, npx, yarn, pnpm, and pnpx commands and checking packages against Aikido Intel before install. Share: https://www.aikido.dev/blog/keyv-and-friends-compromised-in-npm-supply-chain-attack Text Link Scan for malware Start for Free 4.7/ 5 Tired of false positives? Try Aikido like 100k others. Start Now Get a personalized walkthrough Trusted by 100k+ teams Book Now Scan your app for IDORs and real attack paths Trusted by 100k+ teams Start Scanning See how AI pentests your app Trusted by 100k+ teams Start Testing Start Now Similar Posts See all July 31, 2026 • Vulnerabilities & Threats Anthropic&#x27;s Fever Dream: Claude&#x27;s package that stole real keys Anthropic disclosed an agent that pushed real malware to PyPI. We think we found the package, and every mistake in it points back to the AI. # AI # AI Safety # Malware July 22, 2026 • Vulnerabilities & Threats Finding eight high-severity vulnerabilities in NodeBB in six hours Eight high-severity NodeBB vulnerabilities, found by our AI Pentest in six hours. Full technical breakdown of the XSS chains, auth bypasses, and post hijacking. # AI Penetration Testing # Vulnerabilities July 19, 2026