前言

asset_nl7kooy0g_1775881772242 (1).jpg

晚上好,我是 miruky。

2026 年 3 月 31 日,npm 的 Axios 套件(每週約 1 億次下載)遭到供應鏈攻擊。攻擊者透過針對維護者的社交工程竊取 session,並在註冊表上發佈注入惡意相依套件 plain-crypto-js 的 [email protected][email protected]。該套件在 postinstall hook 中部署多段 RAT(遠端存取木馬),在 macOS、Windows、Linux 上安裝完整後門。影響甚至波及 OpenAI 的 macOS 簽章流程,導致憑證輪換的執行。

OWASP Top 10:2025 新增了 Software Supply Chain Failures(軟體供應鏈失效)為第 3 項,顯示相依套件的弱點管理已不再是「建議做」而是「必須做」的階段。

本文精選 8 項可以利用 GitHub 與 npm(package.json)功能,在「下載之前」防止脆弱套件的設定與檢查要點,提供實務導向的落地建議。

之前我也撰寫過關於 AI 程式開發時代的安全性相關長文,本文聚焦於供應鏈防禦的實作面。

最初摘要

對策 防止的風險 適用對象
① Dependabot Alerts 既有相依的已知漏洞 GitHub 設定
② dependabot.yml 相依關係老舊 倉庫設定
③ Dependency Review Action PR 中新增脆弱相依 GitHub Actions
④ 在 CI 中執行 npm audit 建置時漏掉漏洞 CI/CD 管線
⑤ package.json 的 overrides 推移相依(間接相依)的漏洞 package.json
⑥ 管理 package-lock.json 無法重現的建置或檔案被竄改 檔案管理
⑦ npm audit signatures 被竄改的套件 npm 註冊表
⑧ ignore-scripts 惡意 install 腳本 .npmrc

① 開啟 Dependabot Alerts 與安全性更新

GitHub 提供的 Dependabot 會將倉庫的相依關係與 GitHub Advisory Database 比對,發現漏洞時發出警示。若啟用「安全性更新」(Security updates),還會自動建立修補漏洞的 PR。

設定手順

スクリーンショット 2026-04-11 13.20.38.png

於倉庫的 Settings > Advanced Security 中,啟用下列兩項:

  • Dependency graph:相依關係視覺化,為 Dependabot 的基礎。
  • Dependabot alerts:發現漏洞時發出警示。
  • Dependabot security updates:自動建立修補漏洞的 PR。

公開倉庫預設會啟用 Dependency graph 與 Dependabot alerts。私人倉庫則需手動啟用。

警示的優先順序

Dependabot 可能會產生大量警示。GitHub 建議以兩個指標做優先順序判定:CVSS(嚴重度)與 EPSS(被利用的機率)。

  • CVSS:漏洞的技術性嚴重度(0.0–10.0)。CVSS ≥ 9.0 建議立即處理。
  • EPSS:未來 30 天內被利用的機率(0–1)。EPSS ≥ 0.5 建議優先處理。

對 npm 來說,即使漏洞存在於推移相依(間接相依),Dependabot 仍會自動建立包含更新 parent 套件或移除不必要子相依的 PR。

② 用 dependabot.yml 設定相依關係自動更新

②.png

除了安全性更新外,也可以定期檢查版本更新。將 .github/dependabot.yml 放入倉庫,可以讓相依關係維持最新狀態。

基本範例

version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
      day: "monday"
      timezone: "Asia/Tokyo"
    open-pull-requests-limit: 10
    groups:
      # 將 devDependencies 合併成一個 PR
      dev-dependencies:
        dependency-type: "development"
      # production 相依把 patch 與 minor 合併
      production-minor-patch:
        dependency-type: "production"
        update-types:
          - "minor"
          - "patch"

主要設定選項

  • schedule.interval:檢查頻率,可選 daily、weekly、monthly 等。
  • open-pull-requests-limit:同時開啟的 PR 上限(預設 5)。
  • groups:將多個相依更新合併成一個 PR,以避免 PR 爆炸。
  • ignore:排除特定套件或版本範圍。
  • versioning-strategy:版本策略。對應用程式建議使用 increase(將最小版本提升)。

若不使用 groups,Dependabot 可能會為每個相依建立一個 PR,造成通知泛濫。實務上可將 development 與 production 分組管理。

GitHub Actions 的固定版本(Pin)
供應鏈攻擊不只針對 npm 套件,GitHub Actions 亦是攻擊目標。GitHub 在 2026 年 4 月的文件建議,把 Actions 固定為完整的 commit SHA(full-length commit SHA)是最重要的防護措施。

例如,把 GitHub Actions 的自動更新也加入 dependabot.yml:

# dependabot.yml 中加入 GitHub Actions 的自動更新
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"

當 dependabot.yml 含有此設定,Actions 的版本更新會自動提出 PR。但若 PR 中外部修改了 Actions 的 SHA 值,請務必提高警覺:確認該 PR 的來源是可信的 Dependabot。

③ 使用 Dependency Review Action 在 PR 時阻擋脆弱相依

③.png

Dependabot alerts 會掃描既有相依的漏洞,但對於「在 PR 中新增的相依」是否包含漏洞,需在 PR 階段檢查。Dependency Review Action 可在 PR 時檢測並阻擋包含脆弱相依的變更。

工作流程設定範例

name: Dependency Review
on: [pull_request]

permissions:
  contents: read

jobs:
  dependency-review:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Dependency Review
        uses: actions/dependency-review-action@v4
        with:
          fail-on-severity: high
          deny-licenses: GPL-3.0, AGPL-3.0

主要選項說明

  • fail-on-severity:若有指定等級以上的漏洞則讓作業失敗。可選 low、moderate、high、critical。
  • deny-licenses:指定禁止的授權(例如 GPL-3.0、AGPL-3.0)。
  • allow-licenses:允許的授權白名單。

Dependency Review Action 在公開倉庫可免費使用,私人倉庫則需 GitHub Code Security 的授權。

若將此檢查與分支保護規則(或 Ruleset)結合,設為合併的必要條件,則任何包含脆弱相依的 PR 將無法被合併。

④ 將 npm audit 加入 CI/CD 管線

④.png

npm audit 會將 package-lock.json 中列出的所有相依套件與 npm Advisory Database 對照,找出已知漏洞。

CI 工作流程範例

name: Security Audit
on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  audit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '22'
      - run: npm ci
      - run: npm audit --audit-level=high

audit-level 的使用情境

  • critical:只偵測 critical。適合逐步導入既有專案。
  • high:偵測 high 以上。建議用於正式環境 CI/CD。
  • moderate:偵測 moderate 以上。適用於安全需求較嚴格的專案。
  • low:偵測 low 以上。適用於新專案。

注意事項:

  • npm audit 只會偵測漏洞,不會自動修復。若要自動修復,使用 npm audit fix,但在 CI 中通常只做偵測,修復應由人工審查後執行。
  • npm audit fix --force 可能會改變主版本(major),導致相容性破壞,需謹慎使用。
  • npm audit 需 package-lock.json 才能正確運作。請參見下列第 ⑥ 點。

⑤ 使用 package.json 的 overrides 強制修正推移相依

⑤.png

當 Dependabot 無法自動建立修補 PR,或上游套件尚未更新時,可透過 package.json 的 overrides 欄位,強制指定推移相依(間接相依)的版本。

使用範例

{
  "name": "my-app",
  "dependencies": {
    "some-package": "^2.0.0"
  },
  "overrides": {
    "vulnerable-dep": "^1.2.3"
  }
}

overrides 的注意事項

  • 相容的套件管理工具:npm 8.3 以上(Node.js 16.14 以上所附帶)。Yarn 則使用 resolutions 欄位。
  • 可針對特定套件下的相依做覆寫,例如:

    {
    "overrides": {
    "some-package": {
    "vulnerable-dep": "^1.2.3"
    }
    }
    }

    上述寫法只會覆寫 some-package 依賴樹中的 vulnerable-dep,而不影響整個專案其他地方。

  • 風險:強制變更版本可能會破壞 API 相容性,務必執行測試。
  • 建議:把 overrides 當作暫時應急手段;當上游套件正式釋出修正版後,移除 overrides。

⑥ 將 package-lock.json 提交並嚴格管理

⑥.png

package-lock.json 記錄了相依的精確版本、下載來源 URL 與整合性雜湊(integrity)。若不提交 lockfile,就等於允許不可重現的建置。

為何重要(比較)

  • 沒有 lockfile:相同的 ^1.0.0 範圍可能在不同環境安裝不同版本。
  • 有 lockfile:在所有環境安裝相同的版本。
  • 整合性驗證:沒有整合性欄位則無法檢測改動;有 integrity 的 SHA-512 可檢測被竄改。
  • 漏洞追蹤:有 lockfile 時 npm audit 能精確判斷哪些版本受影響。

必守規則

  • 在 CI / 正式環境使用 npm ci
    npm ci 會驗證 package-lock.json 與 package.json 的一致性,若不一致會報錯,避免意外的版本變更。

    開發環境(當需更新 package-lock.json 時):
    npm install

    CI / 正式環境(嚴格依照 lockfile):
    npm ci

  • 不要把 package-lock.json 加入 .gitignore
    有些專案會把 package-lock.json 忽略,這是反模式。即便是 library 開發,npm 官方也建議提交 package-lock.json。node_modules/ 應放入 .gitignore,但 package-lock.json 絕對不要。

⑦ 用 npm audit signatures 驗證套件真實性

⑦.png

npm audit signatures 可以檢查從 npm 註冊表下載的套件是否真的是由註冊表所發佈,驗證數位簽章與 provenance(來歷證明)。

註冊表簽章與 Provenance

  • Registry Signatures(註冊表簽章):npm 註冊表對套件加上的數位簽章,可證明套件未被竄改。
  • Provenance(來歷證明):證明該套件是從哪份原始程式碼、由何種 CI/CD 環境建置而來,並記錄於 Sigstore 的透明度日誌。

執行方式

npm audit signatures

範例輸出:

audited 1267 packages in 6s
1267 packages have verified registry signatures
74 packages have verified attestations

若套件具有 Provenance,npm 套件頁面會顯示綠色的勾選標記。

CI 中的整合

- run: npm ci
- run: npm audit signatures

注意:

  • Provenance 的產生需要套件作者從 GitHub Actions 或 GitLab CI/CD 發佈並簽章,這是套件作者端要配合的動作。
  • 作為使用者,優先選擇具有 Provenance 的套件能提高供應鏈信任度。

另外,npm 在 2025 年 7 月推出 Trusted Publishing(OIDC)的 GA,強烈建議採用 Trusted Publishing。2026 年 3 月的 Axios 事件顯示,舊有長期有效的 npm token 與 Trusted Publishing 同存,可能成為侵害因素之一。套件作者應淘汰舊 token 並完全遷移到 Trusted Publishing。

⑧ 在 .npmrc 設定 ignore-scripts 以防止惡意腳本

⑧.png

Axios 攻擊中的 plain-crypto-js 就是透過在 postinstall 腳本中植入惡意程式碼來實現侵害。執行 npm install 時,無論使用者意圖為何,都可能啟動任意程式碼。

什麼是生命週期腳本(lifecycle scripts)

npm 在安裝時會自動執行下列腳本:

  • preinstall:安裝前執行
  • install:安裝時執行
  • postinstall:安裝後執行

攻擊者可利用 postinstall 執行偷取 token 或植入後門的程式。

設定 ignore-scripts

在專案根目錄建立 .npmrc,加入:

ignore-scripts=true

或在命令列中指定:

npm install --ignore-scripts

副作用與對策

設定 ignore-scripts=true 會阻止所有 postinstall(包括合法用途)執行,例如原生模組建置或下載平臺特定的二進位檔案。常見需要 postinstall 的套件例子:

  • esbuild:下載平台特定的二進位檔。
  • sharp:建置或下載 libvips 的原生二進位檔。
  • bcrypt:編譯 C++ 外掛。

如果需要這類套件,可以先使用 ignore-scripts=true 安裝,之後只對信任的套件單獨執行重建指令:

npm install --ignore-scripts
npm rebuild esbuild
npm rebuild sharp

注意:ignore-scripts=true 並不能完全防止所有供應鏈攻擊,例如在 require() 時執行的程式碼不受此設定影響。因此應與前述的 ①~⑦ 項防護措施併用。

結語

感謝閱讀。

本文整理的 8 項設定如下:

對策 防止的風險 適用對象
① Dependabot Alerts 既有相依的已知漏洞 GitHub 設定
② dependabot.yml 相依關係老舊 倉庫設定
③ Dependency Review Action PR 中新增脆弱相依 GitHub Actions
④ 在 CI 中執行 npm audit 建置時漏掉漏洞 CI/CD 管線
⑤ overrides 推移相依的漏洞 package.json
⑥ package-lock.json 管理 無法重現的建置與檔案被竄改 檔案管理
⑦ npm audit signatures 被竄改的套件 npm 註冊表
⑧ ignore-scripts 惡意 install 腳本 .npmrc

自 2025 年 OWASP Top 10 將供應鏈攻擊列為第 3 名起,至 2026 年已有多個重要 OSS(如 Axios、LiteLLM、Trivy 等)相繼遭受侵害。相依套件的弱點管理是所有開發者應共同面對的課題。你不需要一次導入所有 8 個措施;建議先從 ① 與 ④ 開始,逐步增加防護層。

下次見。

參考連結

GitHub 官方文件

npm 官方文件

GitHub Blog

安全規範

供應鏈攻擊事例


原文出處:https://qiita.com/miruky/items/fcab851c5351f79b481d


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝5   💬6   ❤️3
425
🥈
我愛JS
📝2   💬7   ❤️2
206
🥉
💬1  
4
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
📢 贊助商廣告 · 我要刊登