2026年3月31日,npm 最流行的 HTTP 客户端库 axios 遭遇供应链攻击,两个恶意版本已发布。每一个用 axios 的前端/Node.js 项目都必须立即检查!
📢 事件回顾
攻击时间线(UTC):
| 时间 | 事件 |
|------|------|
| 03-30 05:57 | 攻击者发布 plain-crypto-js@4.2.0(伪装良性包) |
| 03-30 23:59 | 发布恶意版本 plain-crypto-js@4.2.1(含后门) |
| 03-31 00:21 | 发布 axios@1.14.1(注入恶意依赖) |
| 03-31 01:00 | 发布 axios@0.30.4(针对 0.x legacy 版本) |
攻击手法:
-
盗取核心维护者
jasonsaayman的 npm 账号 -
手动发布恶意包,绕过 GitHub Actions CI/CD
-
注入隐蔽依赖
plain-crypto-js@4.2.1 -
自动执行 postinstall 脚本,部署跨平台远控木马(RAT)
-
攻击后自毁痕迹,无声无息窃取数据
⚠️ 这波攻击非常专业:18小时预潜伏、3平台payload、痕迹自毁。是npm生态有史以来最复杂的供应链攻击之一。
🚨 影响范围
-
axios 周下载量:3000万+
-
影响版本:
axios@1.14.1和axios@0.30.4 -
危险行为: 安装时自动下载并执行远控木马,窃取敏感数据
🛡️ 立即检测你的项目
方案一:npm 命令(单项目)
# 检查当前项目安装的 axios 版本
npm list axios --depth=0 2>/dev/null | grep -E "1\.14\.1|0\.30\.4"
# 如果输出为空,说明安全;如果显示版本号,立即处理!
方案二:递归检测脚本(适合排查所有项目)
#!/usr/bin/env python3
"""
Axios 恶意版本检测脚本
检测 Documents 目录下所有前端项目
用法: python3 axios-check.py
"""
import json
import os
import sys
def check_projects(root_path):
"""递归检测所有 package.json 和 package-lock.json"""
home = os.path.expanduser(root_path)
pkgs = []
locks = []
# 收集所有项目文件
for root, dirs, files in os.walk(home):
if 'node_modules' in root:
continue
for f in files:
if f == 'package.json':
pkgs.append(os.path.join(root, f))
elif f == 'package-lock.json':
locks.append(os.path.join(root, f))
print(f"📦 扫描 package.json: {len(pkgs)} 个")
print(f"🔒 扫描 package-lock.json: {len(locks)} 个")
print()
# 恶意版本列表
MALICIOUS_VERSIONS = ['1.14.1', '0.30.4']
# ========== 1. 检查 package.json ==========
print("=" * 70)
print("【1】package.json 直接依赖检查")
print("=" * 70)
risk_pkgs = []
for pkg_file in sorted(pkgs):
try:
with open(pkg_file, 'r', encoding='utf-8') as f:
data = json.load(f)
ver = data.get('dependencies', {}).get('axios', None)
if not ver:
ver = data.get('devDependencies', {}).get('axios', None)
if ver and ver in MALICIOUS_VERSIONS:
risk_pkgs.append((pkg_file, ver))
print(f"🔴 风险: {pkg_file} -> axios@{ver}")
except:
pass
if not risk_pkgs:
print("✅ package.json 检查通过")
# ========== 2. 检查 package-lock.json ==========
print()
print("=" * 70)
print("【2】package-lock.json 实际安装版本检查")
print("=" * 70)
risk_locks = []
for lock_file in sorted(locks):
try:
with open(lock_file, 'r', encoding='utf-8') as f:
data = json.load(f)
packages = data.get('packages', {})
for key, info in packages.items():
if 'axios' in key:
ver = info.get('version', '')
if ver in MALICIOUS_VERSIONS:
risk_locks.append((lock_file, ver, key))
print(f"🔴 风险: {lock_file} -> axios@{ver}")
except:
pass
if not risk_locks:
print("✅ package-lock.json 检查通过")
# ========== 3. 检查恶意依赖 plain-crypto-js ==========
print()
print("=" * 70)
print("【3】恶意依赖 plain-crypto-js 检查")
print("=" * 70)
plain_found = []
for lock_file in sorted(locks):
try:
with open(lock_file, 'r', encoding='utf-8') as f:
data = json.load(f)
packages = data.get('packages', {})
for key, info in packages.items():
if 'plain-crypto-js' in key:
plain_found.append((lock_file, key, info.get('version', '?')))
print(f"🔴 风险依赖: {lock_file} -> {key}")
except:
pass
if not plain_found:
print("✅ 无 plain-crypto-js 恶意依赖")
# ========== 总结 ==========
print()
print("=" * 70)
print("【总结】")
print("=" * 70)
total = len(risk_pkgs) + len(risk_locks) + len(plain_found)
if total == 0:
print("✅ 全部安全!未发现恶意版本")
else:
print(f"⚠️ 发现 {total} 个风险点,请立即处理!")
print()
print("📋 修复方案:")
print(" 1. 删除 node_modules 和 package-lock.json")
print(" 2. 安装安全版本: npm install axios@1.14.0 或 axios@0.30.3")
print(" 3. 重新安装: npm install")
return total
if __name__ == "__main__":
root = sys.argv[1] if len(sys.argv) > 1 else "~/Documents"
check_projects(root)
使用方法:
# 保存为 axios-check.py
chmod +x axios-check.py
# 检测当前目录
python3 axios-check.py .
# 检测 Documents 目录
python3 axios-check.py ~/Documents
# 检测指定目录
python3 axios-check.py /path/to/your/projects
🔧 如果发现风险,这样修复
# 1. 进入项目目录
cd your-project
# 2. 删除安装缓存
rm -rf node_modules package-lock.json
# 3. 重新安装安全版本
npm install axios@1.14.0 # 1.x 系列
# 或
npm install axios@0.30.3 # 0.x 系列
# 4. 验证
npm list axios --depth=0
📝 总结
| 检查项 | 状态 |
|--------|------|
| 恶意版本 1.14.1 / 0.30.4 | ❌ 立即排查 |
| plain-crypto-js 依赖 | ❌ 立即排查 |
| 推荐升级到的安全版本 | ✅ 1.14.0 / 0.30.3 |
📢 呼吁
请转发提醒身边的开发者:
每一个用 axios 的项目都必须检查!攻击者针对的是整个 JavaScript 生态,不要心存侥幸。
🔗 参考链接
本文检测脚本基于真实事件编写,已通过作者本地 120+ 项目验证。