📋 目錄
這篇會把「已確認事實」和「工程推論」分開,讓你用可執行的流程完成判讀、修復與防再發。
前言
axios 是前端與 Node.js 生態最廣泛使用的 HTTP client 之一,一旦出現供應鏈事件,影響不會只停在單一框架,而會擴散到 CI、build agent 與開發者本機。
這次事件最容易踩雷的地方,是團隊把「版本回退」當成結案。實務上,若惡意程式在 install 階段已執行,只有降版並不足夠,還必須做憑證輪替、環境清查與快取隔離。
本文重點不是新聞摘要,而是讓台灣前端團隊能直接採用一套 SOP,在下一次 dependency incident 來時可快速複用。
已確認事實(Facts Only)
以下內容以 2026-03-31 公開資料為準,時間皆為 UTC。
事件與版本事實
- 官方社群 thread:axios issue #10604(
created_at:2026-03-31T03:00:27Z)明確指出axios@1.14.1、axios@0.30.4為受影響版本。 - npm registry 時間戳:
axios@1.14.1:2026-03-31T00:21:58.168Zaxios@0.30.4:2026-03-31T01:00:57.285Z
- 截至 2026-03-31(本稿撰寫時),
npm view axios dist-tags顯示latest為1.14.0。 plain-crypto-js@4.2.1被多方通報為此事件中的惡意關聯依賴;npm registry 顯示其發布時間為2026-03-30T23:59:12.278Z,目前latest為0.0.1-security.0。
需要明確區分的推論
1.14.2是否為「官方已發佈安全版」:截至本文時間點,不能當成既成事實。- 受害範圍是否包含終端使用者:要看你的 pipeline 與 artifact 是否被污染,不能一概而論。
5 分鐘判讀:你現在要先確認什麼?
1. 檢查目前依賴樹(不要只看 package.json)
# npm 專案
npm ls axios plain-crypto-js --all
# pnpm 專案
pnpm ls axios plain-crypto-js --depth Infinity
# Yarn (Berry)
yarn why axios
yarn why plain-crypto-js
重點:不是只看「你宣告了什麼版本」,而是「實際解析安裝了什麼版本」。
2. 用可執行腳本判斷「是否命中 IOC」
// scripts/security/check-compromised-deps.mjs
// 從 stdin 讀取 npm/pnpm 的 JSON 輸出,檢查已知壞版本與關聯 IOC。
import fs from 'node:fs';
const input = fs.readFileSync(0, 'utf8').trim();
if (!input) {
console.error('[SECURITY] empty dependency graph input');
process.exit(2);
}
const parsed = JSON.parse(input);
const roots = Array.isArray(parsed) ? parsed : [parsed];
const badAxios = new Set(['1.14.1', '0.30.4']);
const badPlainCrypto = new Set(['4.2.1']);
const hits = [];
function walk(node, trail = node?.name || 'root') {
if (!node || typeof node !== 'object') return;
const name = node.name;
const version = node.version;
if (name === 'axios' && badAxios.has(version)) {
hits.push(`${trail} -> axios@${version}`);
}
if (name === 'plain-crypto-js' && badPlainCrypto.has(version)) {
hits.push(`${trail} -> plain-crypto-js@${version}`);
}
const deps = node.dependencies;
if (!deps || typeof deps !== 'object') return;
// npm: dependencies 是 object;pnpm json 也可能是 object
for (const [depName, depNode] of Object.entries(deps)) {
const nextTrail = `${trail} > ${depName}`;
walk(depNode, nextTrail);
}
}
for (const root of roots) walk(root);
if (hits.length > 0) {
console.error('[SECURITY] compromised dependency detected:');
for (const hit of hits) console.error(`- ${hit}`);
process.exit(1);
}
console.log('[SECURITY] no known compromised versions found');
# npm
npm ls axios plain-crypto-js --all --json \
| node scripts/security/check-compromised-deps.mjs
# pnpm
pnpm ls axios plain-crypto-js --depth Infinity --json \
| node scripts/security/check-compromised-deps.mjs
3. 快速 IOC 檢查(環境層)
# 僅做快速初篩,正式鑑識請交由資安流程
# 已知網路 IOC(社群通報):sfrclak.com:8000
rg -n "sfrclak\.com|plain-crypto-js" ~/.npm/_logs 2>/dev/null || true
若命中 dependency IOC 或網路 IOC,就要走完整修復流程,不要只做降版。
修復與防再發:可落地 SOP
A. Incident Triage(先隔離、先輪替)
- 暫停可疑 runner / build agent(避免橫向污染)。
- 輪替 npm token、CI secrets、雲端憑證(視為可能外洩)。
- 保留必要證據(logs、lockfile、build metadata)再進行清理。
B. Clean Rebuild(分 package manager 執行)
# npm: 在保留 lockfile 的前提下做可重現安裝(先關 scripts)
npm ci --ignore-scripts
npm ls axios plain-crypto-js --all
# pnpm
pnpm install --frozen-lockfile --ignore-scripts
pnpm ls axios plain-crypto-js --depth Infinity
# Yarn Berry(示例)
yarn install --immutable --mode=skip-build
yarn why axios
若 lockfile 已確認污染,再建立「受控重建分支」重產 lockfile,並經 code review 後才合併。
C. CI Gate(阻擋已知壞版本)
# .github/workflows/security-check.yml
name: Security Dependency Check
on:
pull_request:
push:
branches: [main]
jobs:
dependency-guard:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- name: Install dependencies in safe mode
run: npm ci --ignore-scripts
- name: Check compromised dependencies
run: |
npm ls axios plain-crypto-js --all --json \
| node scripts/security/check-compromised-deps.mjs
- name: Run tests
run: npm test
上面 YAML 可以直接執行,step 結構是合法的,不會出現 - name / - uses 斷裂問題。
D. Policy Hardening(避免下一次重演)
# npm 最低發布年齡(分鐘)
npm config set min-release-age 1440
再加兩個實務策略:
- 發佈端採 Trusted Publisher / OIDC,減少長效 token 風險。
- 依賴更新工具(Dependabot / Renovate)加上 cooldown,不要讓「剛發佈版本」立刻進主幹。
常見問題 / 注意事項
Q1:我已經把 axios 降回 1.14.0,還需要做輪替嗎?
需要。若 install 階段曾執行惡意腳本,降版只處理了「現在的套件狀態」,沒有處理「曾外洩的憑證風險」。
Q2:只檢查 package.json 可以嗎?
不行。事件判讀應以 lockfile 與實際依賴樹為主,因為真正執行的是解析後的 dependency graph。
Q3:--ignore-scripts 應該永久開啟嗎?
建議預設開啟於 CI,一旦有必要 scripts 再建立白名單流程,而不是全域放行。
Q4:這篇的 IOC 會不會過期?
會。IOC 是時間敏感資訊,實務上要搭配你公司 SOC/資安團隊與最新 threat intel 更新。
總結
這次 axios 事件的關鍵教訓,不是「某個套件出事」,而是前端團隊必須把 supply chain security 視為日常工程的一部分。
下一步可以立刻做三件事:
- 把本文的判讀腳本放進 repo,讓 CI 每次都自動擋壞版本。
- 將
min-release-age與 dependency cooldown 寫成團隊政策。 - 針對這次事件補一份 postmortem,沉澱成你們的標準 incident playbook。
只要流程固定,下次再遇到類似事件,你的反應速度和風險控制會快很多。