supply-chain-check

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Supply-chain hygiene audit

供应链卫生审计

A defense-in-depth audit against npm-ecosystem supply-chain attacks (typosquatting, hijacked maintainer accounts, malicious postinstall scripts). Walks the user through their developer machine + the current project + CI workflows, then offers fixes one-by-one with explicit confirmation.
针对npm生态系统供应链攻击(打字错误包、被劫持的维护者账户、恶意postinstall脚本)进行深度防御审计。引导用户检查其开发机器 + 当前项目 + CI工作流,然后逐一提供修复方案并要求明确确认。

Operating rules (read first)

操作规则(请先阅读)

  1. Audit before fix. Always run the full audit and present findings before proposing any change.
  2. Confirm every write. Show the file path and the exact content you will write. Ask y/n. Never batch-apply.
  3. Never execute remote installers. If Safe Chain is missing, print the install command and link; do not run
    curl ... | sh
    yourself.
  4. Never auto-edit CI workflow files. YAML structure varies (matrices, reusable workflows). Print the snippet and the suggested path; let the user place it.
  5. Render policy values at runtime. Read
    policy.json
    from this skill's directory and substitute
    {{VERSION}}
    etc. into templates before showing them.
  6. Surface intentional overrides as warnings, not failures.
    ignore-scripts=false
    is a deliberate choice — flag for review, recommend
    @lavamoat/allow-scripts
    , do not propose flipping.
  1. 先审计后修复。在提出任何更改之前,始终先完成完整审计并呈现结果。
  2. 每次写入都需确认。显示文件路径以及将要写入的准确内容。询问是否确认(y/n)。绝不能批量应用更改。
  3. 绝不执行远程安装程序。如果缺少Safe Chain,请打印安装命令和链接;不要自行运行
    curl ... | sh
  4. 绝不自动编辑CI工作流文件。YAML结构各不相同(矩阵、可复用工作流)。打印代码片段和建议路径;由用户自行放置。
  5. 运行时渲染策略值。从本技能目录读取
    policy.json
    ,并在展示模板前将
    {{VERSION}}
    等变量替换为实际值。
  6. 将有意覆盖项标记为警告而非失败
    ignore-scripts=false
    是故意选择的配置——标记以供审查,建议使用
    @lavamoat/allow-scripts
    ,不要提议修改该配置。

Phase 1 — Detect environment

阶段1 — 检测环境

Run these in parallel:
  • which safe-chain
    — captures G1
  • Read
    ~/.safe-chain/config.json
    (may not exist) — captures G2
  • ls
    the cwd for lockfiles to identify the package manager
  • Check for
    package.json
    — if absent, exit with "Not a JS project, nothing to audit."
Lockfile priority (first match wins):
LockfileManagerExtra check
bun.lockb
bun
pnpm-lock.yaml
pnpmRun
pnpm --version
to branch v9 vs v10+
yarn.lock
+
.yarnrc.yml
yarn berry
yarn.lock
alone
yarn classic v1Emit warning, skip P2, continue with P1/P3/CI
package-lock.json
npm
For yarn classic: emit
⚠ yarn classic detected — no native min-release-age support. Recommend upgrading to Yarn Berry v3+ or switching to pnpm.
Do not propose P2 fixes.
Also check
.github/workflows/
— if it exists, run CI checks. If
.gitlab-ci.yml
/
azure-pipelines.yml
/ etc. exist, emit one
⚠ non-GitHub CI detected — unchecked, see https://github.com/AikidoSec/safe-chain#cicd-integration
.
并行运行以下操作:
  • which safe-chain
    — 获取G1状态
  • 读取
    ~/.safe-chain/config.json
    (可能不存在)—— 获取G2状态
  • 在当前工作目录执行
    ls
    命令查找锁文件,以识别包管理器
  • 检查是否存在
    package.json
    — 如果不存在,输出“非JS项目,无需审计”并退出
锁文件优先级(匹配到第一个即生效):
锁文件包管理器额外检查
bun.lockb
bun
pnpm-lock.yaml
pnpm运行
pnpm --version
以区分v9和v10+版本
yarn.lock
+
.yarnrc.yml
yarn berry
yarn.lock
yarn classic v1发出警告,跳过阶段2,继续执行阶段1/3/CI检查
package-lock.json
npm
对于yarn classic:输出
⚠ 检测到yarn classic — 无原生最小发布时长支持。建议升级到Yarn Berry v3+或切换到pnpm。
不要提议阶段2的修复方案。
同时检查
.github/workflows/
目录 — 如果存在,运行CI检查。如果存在
.gitlab-ci.yml
/
azure-pipelines.yml
/ 其他CI配置文件,输出一条
⚠ 检测到非GitHub CI — 未进行检查,请查看https://github.com/AikidoSec/safe-chain#cicd-integration

Phase 2 — Audit checklist

阶段2 — 审计清单

Present findings as a table. Format:
[✓/✗/⚠] ID — short label — current → expected
.
Global (machine-level):
IDCheck
G1
safe-chain
binary on PATH
G2
~/.safe-chain/config.json
has
minimumPackageAgeHours ≥ 72
Project (repo-level):
IDCheck
P1Lockfile present and not gitignored
P2PM-specific config has policy values (see below)
P3
CONTRIBUTING.md
or
README.md
mentions Safe Chain install
P2 per manager (load thresholds from
policy.json
):
  • npm:
    .npmrc
    contains
    ignore-scripts=true
    ,
    min-release-age=3
    ,
    engine-strict=true
  • pnpm v10+:
    pnpm-workspace.yaml
    contains
    minimumReleaseAge: 4320
    and an explicit
    onlyBuiltDependencies:
    key. Do not flag absence of
    ignore-scripts
    — scripts are disabled by default in v10+.
  • pnpm v9-: treat as npm — expect
    .npmrc
    with
    ignore-scripts=true
    ,
    min-release-age=3
  • yarn berry:
    .yarnrc.yml
    contains
    npmMinimalAgeGate: 3d
    and
    enableScripts: false
  • bun:
    bunfig.toml
    contains
    [install]
    section with
    minimumReleaseAge = 259200
    . Do not flag absence of script-disable — bun disables postinstalls by default.
ignore-scripts=false
handling:
if found in
.npmrc
, emit
⚠ intentional override detected — ensure @lavamoat/allow-scripts is configured as the allowlist (https://github.com/LavaMoat/LavaMoat/tree/main/packages/allow-scripts)
. Mark as warning, not failure. Do not propose flipping.
CI (only if
.github/workflows/
exists):
IDCheck
C1At least one workflow runs a frozen-lockfile install (
npm ci
,
pnpm install --frozen-lockfile
,
yarn install --immutable
,
bun install --frozen-lockfile
) AND has a Safe Chain install step before it
C2Safe Chain installer URL pins a specific version (matches
policy.json#safeChainInstallerVersion
or another concrete version), not
latest
C3The install step does not use bare
npm install
/
yarn install
(without
--immutable
)
C4
SAFE_CHAIN_LOGGING: verbose
is set on the Safe Chain install step
After the table, print:
N passing, M failing, K warnings
. If M+K > 0, ask: "Walk through fixes interactively?" — y/n. If no, stop here.
以表格形式呈现检查结果。格式:
[✓/✗/⚠] ID — 简短标签 — 当前状态 → 预期状态
全局(机器级别):
ID检查项
G1
safe-chain
二进制文件在PATH中
G2
~/.safe-chain/config.json
minimumPackageAgeHours ≥ 72
项目(仓库级别):
ID检查项
P1锁文件存在且未被git忽略
P2包管理器专属配置包含策略值(见下文)
P3
CONTRIBUTING.md
README.md
中提及Safe Chain安装
各包管理器的P2检查项(从
policy.json
加载阈值):
  • npm:
    .npmrc
    包含
    ignore-scripts=true
    min-release-age=3
    engine-strict=true
  • pnpm v10+:
    pnpm-workspace.yaml
    包含
    minimumReleaseAge: 4320
    和明确的
    onlyBuiltDependencies:
    键。不要标记缺少
    ignore-scripts
    的情况——v10+版本默认禁用脚本。
  • pnpm v9-: 按npm处理——预期
    .npmrc
    包含
    ignore-scripts=true
    min-release-age=3
  • yarn berry:
    .yarnrc.yml
    包含
    npmMinimalAgeGate: 3d
    enableScripts: false
  • bun:
    bunfig.toml
    包含
    [install]
    部分,且其中有
    minimumReleaseAge = 259200
    不要标记缺少脚本禁用配置的情况——bun默认禁用postinstall脚本。
ignore-scripts=false
的处理:
如果在
.npmrc
中发现该配置,输出
⚠ 检测到有意覆盖配置 — 确保已将@lavamoat/allow-scripts配置为允许列表(https://github.com/LavaMoat/LavaMoat/tree/main/packages/allow-scripts)
。标记为警告,而非失败。不要提议修改该配置。
CI(仅当
.github/workflows/
存在时):
ID检查项
C1至少有一个工作流执行冻结锁文件的安装命令(
npm ci
pnpm install --frozen-lockfile
yarn install --immutable
bun install --frozen-lockfile
),且在该步骤之前有Safe Chain安装步骤
C2Safe Chain安装器URL固定了特定版本(与
policy.json#safeChainInstallerVersion
或其他具体版本匹配),而非
latest
C3安装步骤未使用裸命令
npm install
/
yarn install
(不带
--immutable
参数)
C4Safe Chain安装步骤设置了
SAFE_CHAIN_LOGGING: verbose
表格展示后,打印:
N项通过,M项失败,K项警告
。如果M+K > 0,询问:"是否逐步引导进行交互式修复?" — y/n。如果选择否,在此处停止。

Phase 3 — Interactive fix loop

阶段3 — 交互式修复循环

Iterate failing checks in this order (least invasive first). For each: show the exact change, ask y/n, apply on yes, skip on no.
按以下顺序处理失败的检查项(从侵入性最低的开始)。对于每个项:显示确切的更改内容,询问是否确认(y/n),确认则应用,否则跳过。

Order

顺序

  1. G2 — Safe Chain global config
    • If
      ~/.safe-chain/config.json
      is missing: show the JSON, confirm, write it.
    • If present but
      minimumPackageAgeHours < 72
      : read existing, show diff, ask before overwriting that key only (preserve other keys).
  2. P2 — PM config
    • Read existing config file if any.
    • Compare key-by-key against the policy.
    • For each missing/incorrect key: show old value vs new value, ask y/n.
    • Use
      Edit
      for surgical merges (preserve unrelated keys, comments, ordering). Only use
      Write
      if the file does not exist.
    • For
      ignore-scripts=false
      in
      .npmrc
      : do not propose change. Print the warning text from Phase 2 and move on.
  3. P3 — CONTRIBUTING/README mention
    • If
      CONTRIBUTING.md
      exists: offer to append
      templates/contributing.snippet.md
      to it.
    • Else if
      README.md
      exists: offer to append to README, OR create
      CONTRIBUTING.md
      — ask which.
    • Else: offer to create
      CONTRIBUTING.md
      from the snippet.
  4. C1–C4 — GitHub Actions (never edit workflow files automatically)
    • For each failing CI check, print the rendered
      templates/github-actions.snippet.yml
      (with
      {{VERSION}}
      substituted from
      policy.json
      ).
    • State which file the user should edit (e.g.
      .github/workflows/ci.yml
      ) and which step it should go before.
    • Do not run Edit or Write on workflow files.
  5. G1 — Safe Chain not installed
    • Print:
      Safe Chain is not on PATH. Install with:
      followed by the official install command and the link
      https://github.com/AikidoSec/safe-chain#installation
      .
    • Do not execute.
After applying each fix, re-run that single check silently and confirm it now passes. If it still fails, surface why and stop the loop.
  1. G2 — Safe Chain全局配置
    • 如果
      ~/.safe-chain/config.json
      不存在:展示JSON内容,确认后写入。
    • 如果存在但
      minimumPackageAgeHours < 72
      :读取现有内容,显示差异,仅在确认后覆盖该键(保留其他键)。
  2. P2 — 包管理器配置
    • 读取现有配置文件(如果存在)。
    • 逐键与策略进行比较。
    • 对于每个缺失/错误的键:显示旧值与新值,询问是否确认。
    • 使用“编辑”进行精准合并(保留无关键、注释、排序)。仅当文件不存在时使用“写入”。
    • 对于
      .npmrc
      中的
      ignore-scripts=false
      :不要提议更改。打印阶段2中的警告文本并继续。
  3. P3 — CONTRIBUTING/README中的提及
    • 如果
      CONTRIBUTING.md
      存在:提议将
      templates/contributing.snippet.md
      追加到该文件中。
    • 如果不存在但
      README.md
      存在:提议追加到README,或创建
      CONTRIBUTING.md
      ——询问选择哪种方式。
    • 如果两者都不存在:提议从代码片段创建
      CONTRIBUTING.md
  4. C1–C4 — GitHub Actions (绝不自动编辑工作流文件)
    • 对于每个失败的CI检查项,打印渲染后的
      templates/github-actions.snippet.yml
      (将
      {{VERSION}}
      替换为
      policy.json
      中的
      safeChainInstallerVersion
      值)。
    • 说明用户应编辑哪个文件(例如
      .github/workflows/ci.yml
      )以及该片段应放置在哪个步骤之前。
    • 不要对工作流文件执行编辑或写入操作。
  5. G1 — 未安装Safe Chain
    • 打印:
      Safe Chain不在PATH中。请使用以下命令安装:
      ,后跟官方安装命令和链接
      https://github.com/AikidoSec/safe-chain#installation
    • 不要执行安装命令。
每个修复应用后,静默重新运行该单项检查并确认现在已通过。如果仍失败,说明原因并停止循环。

Phase 4 — Final summary

阶段4 — 最终总结

Print:
  • Updated pass/fail counts after fixes.
  • A one-line list of files changed in the repo (use
    git diff --stat
    if the cwd is a git repo, else list paths you wrote to).
  • Call out
    ~/.safe-chain/config.json
    separately if you touched it — it is not in the repo.
  • If C1–C4 had failures, remind the user that CI workflow edits are still pending (you printed the snippet but did not apply it).
打印:
  • 修复后的通过/失败计数。
  • 仓库中已更改文件的单行列表(如果当前工作目录是git仓库,使用
    git diff --stat
    ,否则列出已写入的路径)。
  • 如果修改了
    ~/.safe-chain/config.json
    ,单独指出——该文件不在仓库中。
  • 如果C1–C4存在失败项,提醒用户CI工作流编辑仍待完成(已打印代码片段但未应用)。

Templates and policy

模板与策略

Available in this skill directory:
  • policy.json
    — version pins and threshold values. Always load before rendering templates.
  • templates/npmrc
    — full recommended
    .npmrc
    body.
  • templates/pnpm-workspace.snippet.yaml
    — keys to merge into
    pnpm-workspace.yaml
    .
  • templates/yarnrc.snippet.yml
    — keys to merge into
    .yarnrc.yml
    .
  • templates/bunfig.snippet.toml
    — keys to merge into
    bunfig.toml
    .
  • templates/contributing.snippet.md
    — the "Security setup (required)" block.
  • templates/github-actions.snippet.yml
    — Safe Chain + frozen install steps. Substitute
    {{VERSION}}
    from
    policy.json#safeChainInstallerVersion
    before showing.
Templates are written verbatim into user repos. Do not paraphrase them.
本技能目录中提供以下内容:
  • policy.json
    — 版本固定和阈值。渲染模板前务必加载。
  • templates/npmrc
    — 推荐的完整
    .npmrc
    内容。
  • templates/pnpm-workspace.snippet.yaml
    — 需合并到
    pnpm-workspace.yaml
    中的键。
  • templates/yarnrc.snippet.yml
    — 需合并到
    .yarnrc.yml
    中的键。
  • templates/bunfig.snippet.toml
    — 需合并到
    bunfig.toml
    中的键。
  • templates/contributing.snippet.md
    — “安全设置(必填)”模块。
  • templates/github-actions.snippet.yml
    — Safe Chain + 冻结安装步骤。展示前需将
    {{VERSION}}
    替换为
    policy.json#safeChainInstallerVersion
    的值。
模板将原封不动写入用户仓库。请勿改写模板内容。