Community程式設計與開發github.com

hadifarnoud/供應鏈安全

供應鏈與 CI/CD 安全標準 — npm/pnpm 衛生習慣、14 項攻擊分類學(域名搶註、帳號接管、快取投毒、標籤重指向、鎖檔篡改、蠕蟲型惡意軟體)、GitHub Actions 強化、Docker 固定版本、IOC 快速掃描指令與專案稽核結果。適用於任何 npm/pnpm/lockfile 操作、.github/workflows 修改、Dockerfile 或映像固定、MCP/開發工具配置審查,或供應鏈稽核。

供應鏈安全 是什麼?

本技能提供一套全面且實作的供應鏈安全標準,專為 npm/pnpm 生態系、GitHub Actions 工作流程、Docker 容器化工具以及開發者組態檔所設計。其核心為 14 項攻擊分類學—從域名搶註與依賴混淆,到帳號接管、CI/CD 注入,乃至鎖檔篡改與蠕蟲型自我複製惡意軟體—每項均附有具體的偵測指令與強制規則。技能強調`~/.npmrc`中機器層級 gating 的重要性,並釐清 npm 與 pnpm 間常見的設定陷阱,同時記錄經驗證無效的金鑰(如`block-exotic-subdependencies`)以及保留`ignore-scripts=true`作為已知的接受風險。支援的平台涵蓋包含 npm/pnpm 的 Node.js 生態、GitHub Actions(SHA 固定、`pull_request_target`防護)、Docker(摘要固定)以及 MCP/開發工具設定檔審查。技能也提供 IOC(入侵指標)快速掃描檢查清單與優先化修正,使其適用於預防性稽核與事件應變。

相容平台✓Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/hadifarnoud/supply-chain-security/tree/HEAD

Installed? Explore more 程式設計與開發 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

供應鏈安全標準

適用於所有專案。規則審查日期:2026-11-11(Shai-Hulud / Mini Shai-Hulud 蠕蟲後)。


機器層級預設值(~/.npmrc)

minimum-release-age=1440        # pnpm 專用 — 分鐘(1440 = 24小時)
min-release-age=1               # npm 12+ 專用 — 天  (1 = 24小時)

兩種套件管理器使用不同的金鑰名稱與不同的單位。 已於 2026-08-21 透過閱讀各工具的原始碼驗證:pnpm 計算 Date.now() - minimumReleaseAge * 60 * 1e3(分鐘);npm 的 min-release-age 設定定義攜帶 hint: '<days>'。兩行都需要 — 一行無法涵蓋另一行,且將 1440 複製到 npm 金鑰將意味著 1440 天,並會封鎖幾乎所有安裝。

npm 在安裝時會顯示 Unknown user config "minimum-release-age" 並警告將在未來的 major 版本中停止運作。在金鑰存在於 ~/.npmrc 時這是無可避免的:pnpm 11 移除了全域設定寫入功能(pnpm config set --global 現在會導向專案層級的 pnpm-workspace.yaml),因此 ~/.npmrc 是全域 pnpm 閘門唯一能存在的地方。接受此警告;請勿刪除該金鑰。

請勿依賴這些 — 經驗證無效

  • block-exotic-subdependencies — 在 npm 和 pnpm 的原始碼中皆未出現。它從未發揮任何作用。奇異依賴必須透過審查來捕捉,而非此金鑰。

  • ignore-scripts=true — 此技能先前聲稱已全域設定。實際上並未設定,npm config get ignore-scripts 回傳 false,因此生命週期腳本在安裝時確實會執行。

    決定於 2026-08-21:保留關閉狀態。請勿啟用。 Postinstall 是 npm 主要的入侵向量,因此這是一個已知且被接受的缺口 — 而非需要修補的遺漏。在全域開啟它會破壞每個專案的原生建置(esbuild、swc、sharp、node-gyp),且錯誤訊息會遠離問題根源。上述的 24 小時釋出年齡閘門承擔了此風險。如果某個特定專案需要腳本隔離,請在該專案範圍內進行設定 — 永遠不要全域設定。

請根據工具本身而非此檔案來驗證類似的主張 — 審計時這裡的三個條目都是錯誤的。


供應鏈攻擊分類學(稽核前參考)

1. 域名搶註 / 依賴混淆

套件名稱與熱門套件幾乎相同,或公開套件與內部限定名稱相符。僅 2025 年就有 454,648 個惡意 npm 套件被發布。 偵測: 對不熟悉的套件執行 npm info <pkg> | grep -E 'created|repository'。與內部 registry 名稱交叉比對。

2. 維護者帳號接管

攻擊者對維護者進行釣魚,發布包含 post-install 有效載荷的新版本。2025 年 9 月的 Shai-Hulud 攻擊影響了 chalk、debug、ansi-styles(每週 2.6B 下載量)。2026 年 3 月,Axios(每週 1 億+)經由北韓社交工程攻擊受影響。 偵測: npm diff <pkg>@<last-known-good> <pkg>@latest -- package.json scripts — 檢查 patch 版本中是否新增了生命週期腳本。

3. 倉庫劫持 / 命名空間搶註

攻擊者註冊一個廢棄的 GitHub 用戶名或 npm 命名空間,重建倉庫,提供惡意程式碼。 偵測: 檢查 package.json 的 repository 欄位;標記建立時間晚於該套件首次 npm 發布日期的 GitHub 帳號。

4. CI/CD 管道注入(pull_request_target / 快取投毒)

攻擊者針對使用 pull_request_target 且與特權發布作業共用快取的倉庫發起 PR。投毒 pnpm store;下一次釋出工作流程洩漏 npm OIDC token。TanStack 攻擊向量(2025 年 11 月,2026 年 5 月 Mini Shai-Hulud,300+ 套件,每週 1600 萬下載量)。 偵測:

grep -r "pull_request_target" .github/workflows/
grep -r "cache" .github/workflows/ | grep -i "pnpm\|npm\|store"

強制規則: 如果工作流程會檢出 PR 程式碼或與特權作業共用快取,絕對不要使用 pull_request_target。

5. Docker 映像投毒

攻擊者入侵 Docker Hub 憑證,用惡意二進位檔覆寫現有映像標籤(包括 latest)。2026 年 3 月,Trivy aquasec/trivy 的 0.69.4–0.69.6 和 latest 標籤被投毒。2026 年 4 月 KICS — 五個標籤被覆寫;掃描包含機密的 Terraform/K8s 配置。 偵測: docker inspect <image> --format '{{.Id}}' 與配置中固定的摘要比對。 強制規則: 將所有映像固定到 @sha256: 摘要。安全工具映像絕對不要使用 latest。

6. GitHub Actions 標籤重指向

攻擊者入侵 Actions 維護者的 token,移動現有版本標籤指向惡意程式碼。tj-actions/changed-files CVE-2025-30066(2025 年 3 月,23,000+ 倉庫)將所有 CI 機密傾印至日誌。2026 年 5 月:熱門 Actions 標籤被重導向至冒名提交。 偵測:

grep -r "uses:.*@v[0-9]" .github/workflows/   # 標記標籤固定(不良)
grep -r "uses:.*@[a-f0-9]\{40\}" .github/workflows/  # SHA 固定(正確)

強制規則: 將每個第三方 Action 固定到完整的 40 字元提交 SHA,而非版本標籤。actions/*(第一方)可使用 major 版本標籤。

7. 鎖檔篡改 / 完整性繞過(PackageGate 等級)

攻擊者修改鎖檔以替換惡意套件版本,或移除完整性哈希值,使下次安裝時靜默取得不同的 tarball。2026 年 1 月(Koi Security)記錄了六個零日鎖檔漏洞。 偵測:

grep -E '"resolved".*git\+|tarball' package-lock.json pnpm-lock.yaml
grep -v "integrity" pnpm-lock.yaml | grep "resolved"

強制規則: CI 必須使用 pnpm install --frozen-lockfile 或 npm ci — 永遠不要在 CI 中使用裸 npm install。

8. 子依賴陰影

攻擊者針對三層以上的傳遞依賴。@ctrl/tinycolor 是 Shai-Hulud 的傳播節點。 偵測: npm ls --all 2>/dev/null | grep -E "postinstall|preinstall"。在 PR 上使用 socket scan。

9. 社交工程維護者交接

攻擊者冒充招聘人員或商業夥伴以獲取 npm 發布權限。UNC1069(北韓)於 2026 年 3 月針對 Axios 維護者,也嘗試攻擊 Socket CEO、Lodash 創作者、Fastify 負責人。 偵測: 對關鍵依賴執行 npm owner ls <pkg>;監控可疑發布前的新協作者。

10. 抗議軟體(維護者蓄意破壞)

維護者故意注入破壞性程式碼。colors.js v1.4.44–1.4.2(2022 年 1 月,無限迴圈)、node-ipc v10.1.1–10.1.3(2022 年 3 月,針對俄羅斯 IP 刪除檔案)。2026 年 5 月出現三個新的惡意 node-ipc 版本。 偵測:

npm diff <pkg>@<prev> <pkg>@<new> -- lib/
grep -r "networkInterfaces\|geoip\|fs.rmdir\|fs.unlink" node_modules/<pkg>/

將 node-ipc、colors、faker 固定到確切的已知良好版本。

11. 蠕蟲型自我複製惡意軟體

有效載荷竊取 npm token/PAT 並自主發布受害者維護的其他套件的惡意版本。首次觀察到於 2025 年 9 月的 Shai-Hulud;2026 年 5 月的 Mini Shai-Hulud(300+ 套件,每週 1600 萬下載量,同時影響 npm 和 PyPI)。 偵測 IOC:

find .github/workflows -name "*.js"            # 工作流程中的 bundle.js
grep -ri "shai-hulud" .                        # 蠕蟲字串
find node_modules -name "data.json" -newer package.json  # 外洩暫存
find node_modules -name "cloud.json"

12. 潛伏 / 環境條件觸發的有效載荷

僅在存在 AWS_SECRET_ACCESS_KEY、GITHUB_TOKEN 或 CI=true 時啟動的有效載荷 — 可逃避沙箱掃描器。 偵測:

grep -r "process.env.AWS_SECRET\|process.env.GITHUB_TOKEN\|process.env.NPM_TOKEN" node_modules/

標記任何讀取這些變數但缺乏正當理由的套件。

13. 安全工具作為攻擊向量

攻擊者專門針對安全掃描工具(Trivy、KICS、Semgrep),因為它們在 CI 中以提升的權限存取機密和基礎設施配置。Trivy 和 KICS 都在 2026 年 3 月至 4 月間受到攻擊。 強制規則: 將所有安全工具 Docker 映像固定到摘要,而非標籤。透過供應商發布說明,頻外驗證摘要。

14. 非 Registry / CDN 依賴

從 git URL、GitHub tarball 或自訂 CDN(例如 cdn.sheetjs.com)解析的套件繞過了 registry 安全閘門和來源驗證,也不受釋出年齡閘門的保護 — 該閘門僅適用於 registry 版本。部分完全缺少完整性哈希值。沒有任何機制會自動阻止這些;必須透過審查來捕捉。 偵測:

grep -E '"resolved".*github\.com|cdn\.' package-lock.json pnpm-lock.yaml
grep -E '"version":\s*"(git\+|https?:)' package.json

專案層級的 npm/pnpm 衛生習慣

  • 提交鎖檔。CI 必須使用 pnpm install --frozen-lockfile(或 npm ci)。CI 中永遠不要使用裸 npm install。
  • 在 package.json 中固定 packageManager 以鎖定 pnpm/npm 版本。
  • 將受損命名空間中的套件固定到確切版本:@tanstack/*、posthog-node、@mistralai/*、@langchain/mistralai、@ctrl/*、ngx-*、rxnt-*、@zapier/*、@postman/*、@uipath/*、agent-mcp、@semgrep/*、node-ipc、colors、faker。
  • package.json 中沒有萬用字元 "*" 版本。
  • 沒有 pkg.pr.new URL — 這些是暫時的 PR 預覽建置,非不可變的 artifacts。
  • 對於 npm/yarn 專案,在其本機 .npmrc 中鏡像相同的 npmrc 閘門。
  • 新專案偏好使用 pnpm。不要僅為了安全性而遷移運作中的專案。

GitHub Actions 強化

強制規則

  • 絕對不要在以下情況下使用 pull_request_target:工作流程會檢出 PR 程式碼、根據 PR 程式碼執行安裝/建置/測試,或與特權工作流程共用快取。
  • pull_request_target 僅可用於讀取 PR 元資料(標籤、評論、標題)且不進行檢出。
  • 不要在 PR 觸發的作業與發布/釋出作業之間共用快取。
  • CI 中絕對不要對可變動分支(@main、@master)使用 curl | bash 或 wget | sh。始終將安裝腳本固定到特定版本並驗證 checksum。

workflow_run 保護

使用 workflow_run 將特權作業鏈接到父工作流程之後時,if: 必須斷言所有條件:

if: >
  github.event_name == 'workflow_dispatch' ||
  (github.event.workflow_run.conclusion == 'success' &&
   github.event.workflow_run.head_branch == 'main' &&
   github.event.workflow_run.head_repository.full_name == github.repository &&
   github.event.workflow_run.event == 'push')

Action 固定

  • 將每個第三方 Action 固定到完整的 40 字元提交 SHA,而非 @v1/@v6。
  • 為可稽核性加上人類可讀標籤的註解:docker/login-action@65d0a9e # v3
  • 第一方 actions/* 可使用 major 版本標籤。
  • 取得當前 SHA:gh api repos/<owner>/<action>/git/ref/tags/<tag>
  • 自動化操作:npx pin-github-action .github/workflows/*.yml
  • 每個作業最小化 permissions:。預設為 contents: read。僅在發布步驟新增 id-token: write。

npm 發布工作流程

  • 在 npm 帳號上要求 2FA:npm profile enable-2fa auth-and-writes。
  • 使用信任發布(OIDC)而非長期有效的 NPM_TOKEN 機密。
  • 新增 --provenance(或 provenance: true),以便消費者能驗證來源。
  • 僅從由 main 分支標籤推送觸發的 release.yml 發布。永遠不要從 PR 觸發的工作流程發布。

Docker / 容器衛生習慣

  • 將每個 FROM 固定到摘要:FROM node:22-slim@sha256:<hash>
  • 在生產環境 Dockerfile 或 CI 中絕對不要使用 latest 或無標籤的映像。
  • 安全工具映像(Trivy、KICS、Semgrep、Snyk、Grype、Hadolint)風險最高 — 請優先固定這些。
  • 取得當前摘要:docker buildx imagetools inspect node:22-slim --format '{{json .Manifest.Digest}}'
  • 對於私有 registry 映像:使用不可變標籤 + 摘要發布。

開發者工具與配置檔

  • 永遠不要以純文字形式將 API token 或機密儲存在 ~/.cursor/mcp.json、~/.claude/settings.json 或類似的配置檔中。使用環境變數或金鑰鏈。
  • 將 MCP 伺服器套件固定到確切版本([email protected],而非 mcp-remote@latest)。
  • 在任何供應鏈事件發生後,檢查 ~/.vscode/tasks.json 和 ~/.cursor/ 中是否有意外的自動執行鉤子。

偵測 / 監控

  • 在任何包含工作流程的倉庫的 CI 中安裝 zizmor 或 snyk-labs/github-actions-scanner。
  • 在任何發布套件的倉庫(任何可發布的函式庫)上新增 socket.dev GitHub App。
  • 訂閱 npm 安全公告 RSS 和 PyPI 惡意軟體資料來源。

IOC 快速掃描檢查清單

# Shai-Hulud / 蠕蟲 IOC
grep -ri "shai-hulud" .
find .github/workflows -name "*.js"
find node_modules -name "cloud.json"
# 受損工作流程模式
grep -r "pull_request_target" .github/workflows/
grep -r "curl.*|.*sh\|wget.*|.*sh\|base64.*eval" .github/workflows/
# 未固定的 Actions
grep -r "uses:.*@v[0-9]" .github/workflows/
# 鎖檔中的奇異依賴
grep -E '"resolved".*git\+|cdn\.' package-lock.json pnpm-lock.yaml
grep -v integrity pnpm-lock.yaml | grep resolved
# Docker
grep -r "FROM.*:latest\|FROM.*[^@]$" Dockerfile* docker-compose*.yml

相關技能