axios-security-check
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseAxios Supply Chain Attack — Security Check
Axios 供应链攻击 — 安全检查
Attack summary: On March 31, 2026, axios versions and were published via a compromised maintainer account. They silently injected as a dependency, which ran a postinstall script deploying a cross-platform Remote Access Trojan (RAT). Both versions were removed by 03:29 UTC but may remain in local caches or lockfiles.
1.14.10.30.4plain-crypto-js@4.2.1Run all four phases below and produce the report at the end.
攻击概要: 2026年3月31日,攻击者通过被入侵的维护者账号发布了和版本的axios。这两个版本会静默注入作为依赖,该依赖会运行postinstall脚本部署跨平台远程访问木马(RAT)。两个恶意版本均在UTC时间03:29被下架,但可能仍残留在本地缓存或锁文件中。
1.14.10.30.4plain-crypto-js@4.2.1请依次执行以下四个阶段的操作,并在最后生成报告。
Phase 1: Vulnerability Scan
阶段1:漏洞扫描
Search for malicious axios versions in package manifests, lockfiles, and global caches.
Malicious versions: and
1.14.10.30.4在包清单文件、锁文件和全局缓存中搜索恶意axios版本。
恶意版本号: 和
1.14.10.30.41a. Project files under ~
~1a. 用户目录下的项目文件
Search for lockfiles and files (limit depth to avoid excessive crawling):
package.jsonbash
undefined搜索锁文件和文件(限制搜索深度避免过度遍历):
package.jsonbash
undefinedFind package.json files containing axios (depth ≤ 8, skip .git and common noise)
Find package.json files containing axios (depth ≤ 8, skip .git and common noise)
find ~ -maxdepth 8
-not ( -path '/.git/' -o -path '/node_modules//node_modules/*' )
-name "package.json"
-exec grep -l '"axios"' {} ;
-not ( -path '/.git/' -o -path '/node_modules//node_modules/*' )
-name "package.json"
-exec grep -l '"axios"' {} ;
For each match, check if `axios` is pinned to `1.14.1` or `0.30.4`:
```bash
grep -E '"axios":\s*"[^"]*1\.14\.1|[^"]*0\.30\.4"' <path>/package.jsonSearch lockfiles for the malicious versions:
bash
undefinedfind ~ -maxdepth 8
-not ( -path '/.git/' -o -path '/node_modules//node_modules/*' )
-name "package.json"
-exec grep -l '"axios"' {} ;
-not ( -path '/.git/' -o -path '/node_modules//node_modules/*' )
-name "package.json"
-exec grep -l '"axios"' {} ;
对每个匹配的文件,检查axios是否固定为`1.14.1`或`0.30.4`版本:
```bash
grep -E '"axios":\s*"[^"]*1\.14\.1|[^"]*0\.30\.4"' <path>/package.json在锁文件中搜索恶意版本:
bash
undefinedpackage-lock.json / yarn.lock / pnpm-lock.yaml / bun.lock
package-lock.json / yarn.lock / pnpm-lock.yaml / bun.lock
grep -r --include="package-lock.json" --include="yarn.lock"
--include="pnpm-lock.yaml" --include="bun.lock"
-l "axios" ~ 2>/dev/null | head -50
--include="pnpm-lock.yaml" --include="bun.lock"
-l "axios" ~ 2>/dev/null | head -50
For each lockfile found:
```bash
grep -A2 '"axios"' <lockfile> | grep -E "1\.14\.1|0\.30\.4"grep -r --include="package-lock.json" --include="yarn.lock"
--include="pnpm-lock.yaml" --include="bun.lock"
-l "axios" ~ 2>/dev/null | head -50
--include="pnpm-lock.yaml" --include="bun.lock"
-l "axios" ~ 2>/dev/null | head -50
对每个找到的锁文件执行:
```bash
grep -A2 '"axios"' <lockfile> | grep -E "1\.14\.1|0\.30\.4"1b. Global caches
1b. 全局缓存
Check global package manager caches for cached malicious tarballs:
bash
undefined检查全局包管理器缓存中是否存在缓存的恶意安装包:
bash
undefinednpm cache
npm cache
find ~/.npm/_cacache -name "*.json" 2>/dev/null | xargs grep -l '"axios"' 2>/dev/null |
xargs grep -l '"1.14.1"|"0.30.4"' 2>/dev/null
xargs grep -l '"1.14.1"|"0.30.4"' 2>/dev/null
find ~/.npm/_cacache -name "*.json" 2>/dev/null | xargs grep -l '"axios"' 2>/dev/null |
xargs grep -l '"1.14.1"|"0.30.4"' 2>/dev/null
xargs grep -l '"1.14.1"|"0.30.4"' 2>/dev/null
pnpm store (macOS)
pnpm store (macOS)
find ~/Library/pnpm/store -maxdepth 6 -name "package.json" 2>/dev/null |
xargs grep -l '"axios"' 2>/dev/null |
xargs grep -l '"1.14.1"|"0.30.4"' 2>/dev/null
xargs grep -l '"axios"' 2>/dev/null |
xargs grep -l '"1.14.1"|"0.30.4"' 2>/dev/null
find ~/Library/pnpm/store -maxdepth 6 -name "package.json" 2>/dev/null |
xargs grep -l '"axios"' 2>/dev/null |
xargs grep -l '"1.14.1"|"0.30.4"' 2>/dev/null
xargs grep -l '"axios"' 2>/dev/null |
xargs grep -l '"1.14.1"|"0.30.4"' 2>/dev/null
pnpm store (Linux)
pnpm store (Linux)
find ~/.local/share/pnpm/store -maxdepth 6 -name "package.json" 2>/dev/null |
xargs grep -l '"axios"' 2>/dev/null |
xargs grep -l '"1.14.1"|"0.30.4"' 2>/dev/null
xargs grep -l '"axios"' 2>/dev/null |
xargs grep -l '"1.14.1"|"0.30.4"' 2>/dev/null
find ~/.local/share/pnpm/store -maxdepth 6 -name "package.json" 2>/dev/null |
xargs grep -l '"axios"' 2>/dev/null |
xargs grep -l '"1.14.1"|"0.30.4"' 2>/dev/null
xargs grep -l '"axios"' 2>/dev/null |
xargs grep -l '"1.14.1"|"0.30.4"' 2>/dev/null
bun cache
bun cache
find ~/.bun/install/cache -maxdepth 6 -name "package.json" 2>/dev/null |
xargs grep -l '"axios"' 2>/dev/null |
xargs grep -l '"1.14.1"|"0.30.4"' 2>/dev/null
xargs grep -l '"axios"' 2>/dev/null |
xargs grep -l '"1.14.1"|"0.30.4"' 2>/dev/null
---find ~/.bun/install/cache -maxdepth 6 -name "package.json" 2>/dev/null |
xargs grep -l '"axios"' 2>/dev/null |
xargs grep -l '"1.14.1"|"0.30.4"' 2>/dev/null
xargs grep -l '"axios"' 2>/dev/null |
xargs grep -l '"1.14.1"|"0.30.4"' 2>/dev/null
---Phase 2: Malware Artifact Check
阶段2:恶意软件残留检查
2a. plain-crypto-js
presence
plain-crypto-js2a. 排查plain-crypto-js
是否存在
plain-crypto-jsThe malicious dependency used as the attack vector:
bash
find ~ -maxdepth 10 -type d -name "plain-crypto-js" 2>/dev/nullAny result here means was installed — the install-time RAT dropper ran.
plain-crypto-js这是攻击载体使用的恶意依赖:
bash
find ~ -maxdepth 10 -type d -name "plain-crypto-js" 2>/dev/null任何返回结果都说明已被安装,安装时的RAT投放脚本已执行。
plain-crypto-js2b. Platform-specific RAT artifacts
2b. 各平台专属RAT残留文件
Check for files dropped by the RAT dropper. These are fixed paths.
macOS:
bash
ls -la /Library/Caches/com.apple.act.mond 2>/dev/null && echo "FOUND — potential RAT binary" || echo "Not found"Linux:
bash
ls -la /tmp/ld.py 2>/dev/null && echo "FOUND — potential RAT script" || echo "Not found"Windows (if running in WSL or checking a Windows path):
bash
ls -la /mnt/c/ProgramData/wt.exe 2>/dev/null && echo "FOUND — potential RAT binary" || echo "Not found"检查RAT投放脚本释放的文件,这些文件的路径是固定的。
macOS:
bash
ls -la /Library/Caches/com.apple.act.mond 2>/dev/null && echo "FOUND — potential RAT binary" || echo "Not found"Linux:
bash
ls -la /tmp/ld.py 2>/dev/null && echo "FOUND — potential RAT script" || echo "Not found"Windows(如果运行在WSL或检查Windows路径):
bash
ls -la /mnt/c/ProgramData/wt.exe 2>/dev/null && echo "FOUND — potential RAT binary" || echo "Not found"2c. Active C2 connections
2c. 活跃C2连接
Check for live connections to the attacker's command-and-control server:
bash
undefined检查是否存在与攻击者命令与控制(C2)服务器的活跃连接:
bash
undefinedBy IP
By IP
lsof -i @142.11.206.73 2>/dev/null || echo "No connections to C2 IP"
lsof -i @142.11.206.73 2>/dev/null || echo "No connections to C2 IP"
By domain (if DNS resolves)
By domain (if DNS resolves)
lsof -i 2>/dev/null | grep -i sfrclak || echo "No connections to sfrclak.com"
lsof -i 2>/dev/null | grep -i sfrclak || echo "No connections to sfrclak.com"
By port 8000 (C2 port used)
By port 8000 (C2 port used)
lsof -i :8000 2>/dev/null | grep -v "localhost|127.0.0" || echo "No suspicious :8000 connections"
---lsof -i :8000 2>/dev/null | grep -v "localhost|127.0.0" || echo "No suspicious :8000 connections"
---Phase 3: Package Manager Security Audit
阶段3:包管理器安全审计
Detect which package managers are installed and check their security-relevant configuration. Read global config files and project-level config/manifest files in the current directory.
检测已安装的包管理器,检查其与安全相关的配置。读取全局配置文件,以及当前目录下的项目级配置/清单文件。
3a. Detect installed package managers
3a. 检测已安装的包管理器
bash
which npm && npm --version
which pnpm && pnpm --version
which bun && bun --version
which yarn && yarn --versionbash
which npm && npm --version
which pnpm && pnpm --version
which bun && bun --version
which yarn && yarn --version3b. npm
3b. npm
Config files to read:
- Global:
~/.npmrc - Project: in current directory
.npmrc
bash
npm config get ignore-scripts
npm config get min-release-age
npm config get audit| Setting | Secure value | Default | Effect |
|---|---|---|---|
| | | Disables all lifecycle scripts for all packages |
| e.g. | unset | Refuses to install package versions published more recently than the threshold — blocks day-zero malicious publishes |
| | | Checks installed packages against known vulnerability advisories |
Note: npm has no per-package script allowlist — is all-or-nothing.
ignore-scripts需要读取的配置文件:
- 全局:
~/.npmrc - 项目:当前目录下的
.npmrc
bash
npm config get ignore-scripts
npm config get min-release-age
npm config get audit| 配置项 | 安全值 | 默认值 | 作用 |
|---|---|---|---|
| | | 禁用所有包的所有生命周期脚本 |
| 例如 | 未设置 | 拒绝安装发布时间短于阈值的包版本,可拦截零日恶意发布 |
| | | 对照已知漏洞通告检查已安装的包 |
注意:npm没有包粒度的脚本允许列表,是全有或全无的配置。
ignore-scripts3c. pnpm
3c. pnpm
Config files to read:
- Global: (pnpm reads this too) and
~/.npmrcpnpm config list - Project: ,
.npmrcpnpm-workspace.yaml - →
package.jsonfieldpnpm
bash
pnpm config get ignore-scripts 2>/dev/null
pnpm config get ignoreDepScripts 2>/dev/null
pnpm config get minimumReleaseAge 2>/dev/null
pnpm config get blockExoticSubdeps 2>/dev/null
pnpm config get onlyBuiltDependencies 2>/dev/null
pnpm config get neverBuiltDependencies 2>/dev/null
pnpm config get strictDepBuilds 2>/dev/null
pnpm config get dangerouslyAllowAllBuilds 2>/dev/nullAlso read project-level files:
bash
cat pnpm-workspace.yaml 2>/dev/null | grep -E "minimumReleaseAge|blockExoticSubdeps|onlyBuiltDependencies|allowBuilds|neverBuiltDependencies|strictDepBuilds|ignoreDepScripts|dangerouslyAllowAllBuilds"
cat package.json 2>/dev/null | python3 -c "import sys,json; d=json.load(sys.stdin); print(json.dumps(d.get('pnpm',{}), indent=2))" 2>/dev/null| Setting | Secure value | Default | Effect |
|---|---|---|---|
| e.g. | | Refuses packages published more recently than the threshold — blocks day-zero attacks like this one |
| scoped list | unset | Packages exempt from the age check |
| | | Transitive deps must come from a registry; blocks git/tarball URL subdependencies injected by attackers |
| | | Skips lifecycle scripts in dependencies only; project scripts still run |
| | | Skips all lifecycle scripts (dependencies and project) |
| Explicit allowlist | unset | Only listed packages may run install scripts — all others blocked |
| Per-package map | unset | Newer alternative to |
| Blocklist of known-bad packages | unset | Explicitly prevents listed packages from running scripts |
| | | Install fails if any dependency has unreviewed build scripts — forces explicit approval |
| | | Flag if this is |
需要读取的配置文件:
- 全局:(pnpm也会读取该文件)和
~/.npmrc的输出pnpm config list - 项目:、
.npmrcpnpm-workspace.yaml - →
package.json字段pnpm
bash
pnpm config get ignore-scripts 2>/dev/null
pnpm config get ignoreDepScripts 2>/dev/null
pnpm config get minimumReleaseAge 2>/dev/null
pnpm config get blockExoticSubdeps 2>/dev/null
pnpm config get onlyBuiltDependencies 2>/dev/null
pnpm config get neverBuiltDependencies 2>/dev/null
pnpm config get strictDepBuilds 2>/dev/null
pnpm config get dangerouslyAllowAllBuilds 2>/dev/null同时读取项目级文件:
bash
cat pnpm-workspace.yaml 2>/dev/null | grep -E "minimumReleaseAge|blockExoticSubdeps|onlyBuiltDependencies|allowBuilds|neverBuiltDependencies|strictDepBuilds|ignoreDepScripts|dangerouslyAllowAllBuilds"
cat package.json 2>/dev/null | python3 -c "import sys,json; d=json.load(sys.stdin); print(json.dumps(d.get('pnpm',{}), indent=2))" 2>/dev/null| 配置项 | 安全值 | 默认值 | 作用 |
|---|---|---|---|
| 例如 | | 拒绝发布时间短于阈值的包,可拦截本次这类零日攻击 |
| 限定范围的列表 | 未设置 | 不受年龄检查限制的包列表 |
| | | 传递依赖必须来自注册表,拦截攻击者注入的git/压缩包URL形式的依赖 |
| | | 仅跳过依赖的生命周期脚本,项目脚本仍可运行 |
| | | 跳过所有生命周期脚本(包括依赖和项目) |
| 显式允许列表 | 未设置 | 仅列表中的包可以运行安装脚本,其余全部拦截 |
| 包粒度映射 | 未设置 | |
| 已知风险包的拦截列表 | 未设置 | 显式禁止列表中的包运行脚本 |
| | | 如果任何依赖存在未审核的构建脚本,安装就会失败,强制显式审批 |
| | | 如果该值为 |
3d. bun
3d. bun
Config files to read:
- Global:
~/.bunfig.toml - Project:
bunfig.toml - Project →
package.jsonfieldtrustedDependencies
bash
cat ~/.bunfig.toml 2>/dev/null || echo "No global bunfig.toml"
cat bunfig.toml 2>/dev/null || echo "No project bunfig.toml"
cat package.json 2>/dev/null | python3 -c "import sys,json; d=json.load(sys.stdin); print(json.dumps(d.get('trustedDependencies','not set'), indent=2))" 2>/dev/null| Setting | Location | Secure value | Default | Effect |
|---|---|---|---|---|
| | Explicit allowlist | Top-500 npm packages auto-trusted | Only listed packages may run lifecycle scripts; any package not on this list is blocked |
| | e.g. | unset | Refuses packages newer than the threshold |
| | Scoped allowlist | unset | Alternative/additional script execution control |
Note: Bun's default is more secure than npm — scripts are blocked for packages not in the built-in top-500 allowlist. An explicit field in overrides this and should be reviewed carefully.
trustedDependenciespackage.json需要读取的配置文件:
- 全局:
~/.bunfig.toml - 项目:
bunfig.toml - 项目→
package.json字段trustedDependencies
bash
cat ~/.bunfig.toml 2>/dev/null || echo "No global bunfig.toml"
cat bunfig.toml 2>/dev/null || echo "No project bunfig.toml"
cat package.json 2>/dev/null | python3 -c "import sys,json; d=json.load(sys.stdin); print(json.dumps(d.get('trustedDependencies','not set'), indent=2))" 2>/dev/null| 配置项 | 位置 | 安全值 | 默认值 | 作用 |
|---|---|---|---|---|
| | 显式允许列表 | 自动信任npm前500热门包 | 仅列表中的包可以运行生命周期脚本,不在列表中的包全部被拦截 |
| | 例如 | 未设置 | 拒绝发布时间短于阈值的包 |
| | 范围限定的允许列表 | 未设置 | 替代/补充的脚本执行控制机制 |
注意:Bun的默认配置比npm更安全,不在内置前500允许列表中的包的脚本会被拦截。中显式的字段会覆盖默认配置,需要仔细审核。
package.jsontrustedDependencies3e. Yarn (Berry)
3e. Yarn (Berry)
Config files to read:
- Global:
~/.yarnrc.yml - Project:
.yarnrc.yml
bash
cat ~/.yarnrc.yml 2>/dev/null | grep -E "enableScripts|dependenciesMeta" || echo "No global .yarnrc.yml"
cat .yarnrc.yml 2>/dev/null | grep -E "enableScripts|dependenciesMeta" || echo "No project .yarnrc.yml"| Setting | Secure value | Default | Effect |
|---|---|---|---|
| | | Disables all lifecycle scripts globally; re-enable per-package via |
需要读取的配置文件:
- 全局:
~/.yarnrc.yml - 项目:
.yarnrc.yml
bash
cat ~/.yarnrc.yml 2>/dev/null | grep -E "enableScripts|dependenciesMeta" || echo "No global .yarnrc.yml"
cat .yarnrc.yml 2>/dev/null | grep -E "enableScripts|dependenciesMeta" || echo "No project .yarnrc.yml"| 配置项 | 安全值 | 默认值 | 作用 |
|---|---|---|---|
| | | 全局禁用所有生命周期脚本,可通过 |
3f. CI/CD workflow check
3f. CI/CD 工作流检查
If exists, check install commands for hardening flags:
.github/workflows/bash
grep -r --include="*.yml" --include="*.yaml" \
-E "npm install|npm ci|pnpm install|bun install|yarn install" \
.github/ 2>/dev/null | head -20Flags to look for: , (vs ), .
--ignore-scriptsnpm cinpm install--frozen-lockfile如果存在目录,检查安装命令的安全加固 flags:
.github/workflows/bash
grep -r --include="*.yml" --include="*.yaml" \
-E "npm install|npm ci|pnpm install|bun install|yarn install" \
.github/ 2>/dev/null | head -20需要关注的flags:、(对比)、。
--ignore-scriptsnpm cinpm install--frozen-lockfilePhase 4: Report
阶段4:报告
Produce a clean report with the following structure. Be explicit about each finding — "not found" is a valid and important result.
undefined按照以下结构生成清晰的报告,每个结果都要明确说明,「未找到」是有效且重要的结果。
undefinedAxios Supply Chain Attack — Security Report
Axios 供应链攻击 — 安全报告
Generated: <date>
生成时间:<date>
Vulnerability Scan
漏洞扫描结果
- Affected axios versions found in project files: <list paths or "None found">
- Affected axios versions found in global caches: <list or "None found">
- 项目文件中发现的受影响axios版本:<列出路径或「未找到」>
- 全局缓存中发现的受影响axios版本:<列出路径或「未找到」>
Malware Artifacts
恶意软件残留结果
- plain-crypto-js present: <Yes — <path> | No>
- macOS RAT binary (/Library/Caches/com.apple.act.mond): <Found | Not found>
- Linux RAT script (/tmp/ld.py): <Found | Not found>
- Windows RAT binary (%PROGRAMDATA%\wt.exe): <Found | Not found>
- Active C2 connections (sfrclak.com:8000 / 142.11.206.73): <Active | None detected>
- plain-crypto-js是否存在:<是 — <路径> | 否>
- macOS RAT二进制文件(/Library/Caches/com.apple.act.mond):<已找到 | 未找到>
- Linux RAT脚本(/tmp/ld.py):<已找到 | 未找到>
- Windows RAT二进制文件(%PROGRAMDATA%\wt.exe):<已找到 | 未找到>
- 活跃C2连接(sfrclak.com:8000 / 142.11.206.73):<活跃 | 未检测到>
Package Manager Security Audit
包管理器安全审计结果
For each installed package manager, report the key settings. Use "✓ set", "✗ unset", or the actual value.
npm <version>:
- : <value>
ignore-scripts - : <value or "not set">
min-release-age - : <value>
audit
pnpm <version>:
- : <value or "not set">
minimumReleaseAge - : <value>
blockExoticSubdeps - : <value>
ignoreDepScripts - /
onlyBuiltDependencies: <set with N packages | not set>allowBuilds - : <value>
strictDepBuilds - : <value — flag if true>
dangerouslyAllowAllBuilds
bun <version>:
- in package.json: <explicit list | using defaults>
trustedDependencies - in bunfig.toml: <value or "not set">
[install].minimumReleaseAge
yarn <version>:
- : <value or "not set (defaults to true)">
enableScripts
对每个已安装的包管理器,报告关键配置。使用「✓ 已设置」、「✗ 未设置」或实际值填写。
npm <版本号>:
- :<值>
ignore-scripts - :<值或「未设置」>
min-release-age - :<值>
audit
pnpm <版本号>:
- :<值或「未设置」>
minimumReleaseAge - :<值>
blockExoticSubdeps - :<值>
ignoreDepScripts - /
onlyBuiltDependencies:<已设置N个包 | 未设置>allowBuilds - :<值>
strictDepBuilds - :<值 — 若为true请标记>
dangerouslyAllowAllBuilds
bun <版本号>:
- package.json中的:<显式列表 | 使用默认配置>
trustedDependencies - bunfig.toml中的:<值或「未设置」>
[install].minimumReleaseAge
yarn <版本号>:
- :<值或「未设置(默认为true)」>
enableScripts
Recommendations
修复建议
[Prioritized list based on findings above — see guidance below]
undefined[根据上面的发现给出优先级排序的建议,参考下方指南]
undefinedRecommendation guidance (include relevant items only)
建议指南(仅包含相关项)
If compromised (artifacts found or C2 connections detected):
- Treat as full system breach — isolate immediately
- Rotate all credentials: API keys, SSH keys, cloud credentials, npm tokens, GitHub tokens
- Rebuild from a clean snapshot if possible
- Review logs for C2 traffic to /
sfrclak.com:8000between March 31 00:00–04:00 UTC 2026142.11.206.73
If malicious axios version found (no artifacts):
- Remove from lockfile: downgrade to (last safe 1.x) or
axios@1.7.9(last safe 0.x)axios@0.29.0 - Delete from
plain-crypto-jsand lockfilenode_modules - Run fresh install: /
pnpm install/npm cibun install
For pnpm users:
- Set in
minimumReleaseAge— even 24h (1440 min) would have blocked this attack, which published and was removed within ~3 hours:pnpm-workspace.yamlyamlminimumReleaseAge: 1440 # 1 day in minutes - Enable — the injected
blockExoticSubdeps: truecould have been delivered via tarball URL; this blocks non-registry transitive deps:plain-crypto-jsyamlblockExoticSubdeps: true - Use or
onlyBuiltDependenciesto allowlist only packages that legitimately need scripts. PreferallowBuilds(pnpm 9+) as it supports version constraints:allowBuildsyaml# pnpm-workspace.yaml onlyBuiltDependencies: - esbuild - sharp - "@swc/core" - Enable so installs fail loudly if an unknown package tries to run scripts:
strictDepBuilds: trueyamlstrictDepBuilds: true - Use if you need to run your own project scripts but want to block all dependency scripts (more surgical than
ignoreDepScripts: true)ignoreScripts - Verify is not set to
dangerouslyAllowAllBuilds— if it is, remove it immediatelytrue
For npm users:
- Set in
min-release-age— this is the single most effective preventive control for day-zero attacks:.npmrc(259200 seconds = 3 days; even 3600 = 1 hour would have blocked this attack)min-release-age=259200 - Add to
ignore-scripts=truefor CI environments (may break packages with legitimate build steps — test first).npmrc - Use instead of
npm ciin CI — it respects lockfiles exactly and fails on driftnpm install - Run in CI pipelines
npm audit --audit-level=high
For bun users:
- Set an explicit in
trustedDependenciesrather than relying on bun's default top-500 list. Review which packages in your dependency tree genuinely need scripts:package.jsonjson{ "trustedDependencies": ["esbuild", "sharp"] } - Set in
minimumReleaseAge:bunfig.tomltoml[install] minimumReleaseAge = 259200 # 3 days in seconds
For yarn users (Berry):
- Add to :
.yarnrc.ymlenableScripts: false - Re-enable per package via for packages with legitimate build scripts
dependenciesMeta
General (all users):
- Always commit lockfiles to version control — they are the source of truth for installed versions
- Use /
--frozen-lockfileflags in CI to prevent lockfile drift--ci - Consider Socket.dev or Snyk for continuous supply chain monitoring that catches malicious packages before they install
如果已被入侵(发现恶意残留或C2连接):
- 视为完整系统入侵,立即隔离
- 轮换所有凭证:API密钥、SSH密钥、云凭证、npm令牌、GitHub令牌
- 尽可能从干净快照重建系统
- 排查2026年3月31日UTC 00:00–04:00期间到/
sfrclak.com:8000的C2流量日志142.11.206.73
如果发现恶意axios版本(无恶意残留):
- 从锁文件中移除恶意版本,降级到(1.x最新安全版)或
axios@1.7.9(0.x最新安全版)axios@0.29.0 - 从和锁文件中删除
node_modulesplain-crypto-js - 执行全新安装:/
pnpm install/npm cibun install
pnpm用户建议:
- 在中设置
pnpm-workspace.yaml,即使是24小时(1440分钟)也能拦截本次攻击,本次攻击从发布到下架仅用了约3小时:minimumReleaseAgeyamlminimumReleaseAge: 1440 # 1天,单位分钟 - 启用,注入的
blockExoticSubdeps: true可能通过压缩包URL投放,该配置可拦截非注册表来源的传递依赖:plain-crypto-jsyamlblockExoticSubdeps: true - 使用或
onlyBuiltDependencies仅允许确实需要运行脚本的包,优先使用allowBuilds(pnpm 9+),支持版本约束:allowBuildsyaml# pnpm-workspace.yaml onlyBuiltDependencies: - esbuild - sharp - "@swc/core" - 启用,如果有未知包尝试运行脚本,安装会明确报错:
strictDepBuilds: trueyamlstrictDepBuilds: true - 如果需要运行项目自身的脚本但要拦截所有依赖脚本,可以使用,比
ignoreDepScripts: true更灵活ignoreScripts - 确认未设置为
dangerouslyAllowAllBuilds,如果已设置请立即删除true
npm用户建议:
- 在中设置
.npmrc,这是防范零日攻击最有效的单一控制措施:min-release-age(259200秒=3天,即使设置3600=1小时也能拦截本次攻击)min-release-age=259200 - 在CI环境的中添加
.npmrc(可能会破坏有合法构建步骤的包,请先测试)ignore-scripts=true - 在CI中使用替代
npm ci,它会严格遵循锁文件,出现漂移时直接失败npm install - 在CI流水线中运行
npm audit --audit-level=high
bun用户建议:
- 在中设置显式的
package.json,不要依赖bun默认的前500热门包列表,审核依赖树中确实需要运行脚本的包:trustedDependenciesjson{ "trustedDependencies": ["esbuild", "sharp"] } - 在中设置
bunfig.toml:minimumReleaseAgetoml[install] minimumReleaseAge = 259200 # 3天,单位秒
Yarn(Berry)用户建议:
- 在中添加:
.yarnrc.ymlenableScripts: false - 对有合法构建脚本的包,通过单独启用脚本
dependenciesMeta
通用建议(所有用户):
- 始终将锁文件提交到版本控制,它们是已安装版本的唯一可信来源
- 在CI中使用/
--frozen-lockfileflags防止锁文件漂移--ci - 考虑使用Socket.dev或Snyk进行持续供应链监控,在恶意包安装前就完成拦截