关于 supply-chain-hardening
面向管理 npm 和 bun 依赖的团队(包括新闻工具链)的供应链加固 Skill。它结合版本发布冷却期、绕过时的沙箱扫描和跳过安装脚本,并说明这些措施未覆盖的风险。
主要功能
- 01配置 npm 和 bun 版本冷却期
- 02在沙箱中扫描候选包
- 03绕过冷却期安装时跳过生命周期脚本
- 04检查包内容及已知漏洞
- 05说明锁文件和传递依赖的限制
适用场景
- 01加固新机器上的依赖安装
- 02绕过冷却期时审查软件包
- 03降低 postinstall 载荷执行风险
- 04审计锁文件和现有依赖
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ jamditis/ claude-skills-journalism --skill supply-chain-hardening安装后在 Claude Code 中输入/supply-chain-hardening确认已加载。
附带文件agents/openai.yaml
详细介绍
供应链加固
保护新闻工具链,抵御常见的 npm/bun 供应链攻击模式:维护者账号或 CI 流水线遭到入侵,恶意版本发布,随后机器在有人察觉之前安装了该版本。近期案例:Mini Shai-Hulud TanStack 攻击(2026-05-11) 入侵了 42 个 @tanstack/* 软件包中的 84 个版本,并通过 postinstall 脚本窃取 AWS / GCP / Vault / GitHub / SSH 凭据。
防御措施采用分层设计,并刻意保持简单:
- 安装时冷却期,仅安装发布超过 N 天的软件包版本(默认 7 天)。这是主要防御措施。冷却期结束时,安全社区几乎总会标记出遭入侵的版本,软件包注册表也会撤下这些版本。
- 沙箱化的安装前扫描,当必须绕过冷却期时(CVE 补丁、新依赖、紧急安装),通过静态分析扫描检查候选 tarball,查找供应链恶意软件的诊断特征。扫描会在
bwrap/firejail/unshare中运行,防止恶意软件逃出检查环境。 - 安装时使用
--ignore-scripts,postinstall 是首要攻击途径。每次绕过冷却期安装时,都跳过生命周期脚本。
这三项措施结合起来,即使没有人工介入,也能在未经修改的笔记本电脑上阻止 Mini Shai-Hulud TanStack 攻击。
配置冷却期
已验证的配置键(npm v11+ 和 bun 1.3+):
| 管理器 | 文件 | 键 | 单位 | 排除键 |
|---|---|---|---|---|
| npm | ~/.npmrc(或项目 .npmrc) | min-release-age | 天 | 暂无,已在 npm/cli#8994 中提议 |
| bun | ~/.bunfig.toml(或项目 bunfig.toml) | [install] minimumReleaseAge | 秒 | [install] minimumReleaseAgeExcludes = [](精确名称,不支持 glob) |
最简配置:
# ~/.npmrc
min-release-age=7
# ~/.bunfig.toml
[install]
minimumReleaseAge = 604800 # 7 days
minimumReleaseAgeExcludes = []
需要 npm 11+。 较旧版本的 npm 会静默忽略未知键,因此配置看起来正确,实际却不起作用。使用 npm --version 和 npm config get min-release-age 检查(应输出 7,而不是 null)。
按命令绕过
当冷却期阻止了你确实需要的安装时:
npm install <pkg>@<version> --min-release-age=0 --ignore-scripts
bun add <pkg>@<version> --minimum-release-age=0 --ignore-scripts
bun add --minimum-release-age=0 CLI 标志在 1.3+ 中可用,尽管文档没有列出;它遵循 bun 的 bunfig key → kebab-case flag 惯例。
绕过时务必同时使用 --ignore-scripts。 在供应链恶意软件中,postinstall 是最常见的载荷执行途径(Mini Shai-Hulud、event-stream、ua-parser-js、coa 都使用了它)。确实需要 postinstall 的原生模块,可以在人工阅读审查脚本后手动运行:
(cd node_modules/<pkg> && cat package.json | jq .scripts) # eyeball it
(cd node_modules/<pkg> && npm run postinstall) # run if it checks out
何时在绕过前扫描
扫描针对的是危险时刻:你已经决定绕过冷却期,需要进行合理性检查。该技能提供了一个实现这些启发式检查的参考脚本(scripts/hotpatch.example.sh)。请根据你的机器进行调整;Bash 方案假定使用 bwrap(Linux);macOS 用户可替换为 sandbox-exec,也可以跳过沙箱层,但需接受文档中说明的权衡。
扫描应执行的静态检查(每项都有真实攻击作为依据):
| 检查 | 诊断对象 | 严重性 |
|---|---|---|
optionalDependencies / dependencies 中包含 github: 或 git+ URL | Mini Shai-Hulud(通过 github:tanstack/router#<sha> 引用交付载荷) | RED |
软件包根目录中存在未被 main/module/exports/bin/files 引用的大型 JS 文件 | 植入载荷模式(Mini Shai-Hulud 中的 router_init.js) | RED |
| 解包大小超过上一稳定版本的 3 倍 | 隐藏大批量载荷 | RED |
fileCount 增量为 1–4,且大小增长超过 2 倍 | 单个植入文件 | RED |
存在 preinstall/install/postinstall/prepare 脚本 | 生命周期脚本攻击途径(event-stream、ua-parser-js 等) | YELLOW |
JS 文件引用 .ssh/、.aws/、.npmrc、GITHUB_TOKEN、AWS_SECRET、kube 配置 | 凭据外泄 | YELLOW |
npm 注册表将版本标记为 deprecated,且措辞中包含 "security"/"compromised"/"malicious" | 维护者/注册表撤回 | RED |
OSV.dev 报告 <pkg>@<version> 存在已知漏洞 | 已披露的 CVE | RED(取决于严重性) |
为什么预发布版本不会纳入大小变化基线: dev/beta/rc 版本的大小与稳定版本差异很大,会产生误报。
冷却期无法防范的情况
请如实向你为其配置此功能的人说明其局限:
- 处于冷却期内的新恶意版本会被拦截,但如果恶意版本也通过了冷却期(罕见但有可能,例如遭入侵后超过 7 天仍未被发现),单靠冷却期就无济于事。扫描能捕获其中大多数情况。
- 传递依赖。你安装的干净
<pkg>可能会引入遭入侵的传递依赖。防范措施:针对解析后的依赖树进行扫描(npm audit、osv-scanner),并在全局保持冷却期启用,让传递依赖的解析也必须等待。 - 针对现有锁文件执行
npm ci。冷却期适用于解析阶段,而非安装已固定版本。如果锁文件固定了遭入侵的版本,npm ci就会安装该版本。缓解措施:在 CI 中使用osv-scanner --lockfile=package-lock.json扫描锁文件。 node_modules中已存在的遭入侵软件包。加固只保护之后的安装,不会追溯既往。请单独审计现有依赖(npm audit、osv-scanner,以及手动检查依赖树中近期发布的依赖)。
新机器快速入门工作流
- 确认 npm >= 11:
npm --version。如果版本较旧,请升级(sudo npm i -g npm@latest;如果自行升级会发生竞争问题,可使用 tarball 替换)。 - 使用上述配置编写
~/.npmrc和~/.bunfig.toml。 - 验证:
npm config get min-release-age返回7。cat ~/.bunfig.toml显示[install]块。 - 将
scripts/hotpatch.example.sh复制到由用户拥有的工具目录。使其可执行。使用随附的 Mini Shai-Hulud 合成样例运行./hotpatch.sh --self-test,确认启发式检查能够触发。 - 在团队成员都能找到的地方记录绕过工作流。此技能的前提是绕过操作应当罕见且经过审核,而不是默认做法。
威胁模型:防御范围与不防御的内容
| 防御对象 | 不防御的内容 |
|---|---|
| 维护者账户遭入侵(npm 令牌被盗) | 专门设计为等待冷却期结束后再发动的定向攻击 |
| CI/CD 流水线遭劫持(Mini Shai-Hulud、有效的 OIDC 令牌、带 SLSA 证明的恶意代码) | 锁文件中已固定版本的传递依赖遭入侵 |
仿冒包名(相似的包名),配合 npm pkg fix 和锁文件审查时 | 由你编写并包含在自己的开发依赖项中的恶意代码 |
postinstall 载荷执行(冷却期加上 --ignore-scripts,双重保险) | 运行时供应链攻击(例如从 CDN 动态加载恶意代码) |
随手安装全新的传递依赖(npm install) | 注册表本身遭入侵(极少发生;不在防护范围内) |
延伸阅读
- StepSecurity 对 Mini Shai-Hulud 的原始分析(TanStack 攻击,2026-05-11):https://www.stepsecurity.io/blog/mini-shai-hulud-is-back-a-self-spreading-supply-chain-attack-hits-the-npm-ecosystem
- npm
min-release-age配置:https://docs.npmjs.com/cli/v11/using-npm/config - bun
minimumReleaseAge配置:https://bun.com/docs/runtime/bunfig - OSV.dev API(免费,无需认证):https://osv.dev/docs/#tag/api
- 早期 Shai-Hulud 蠕虫的背景信息:https://github.com/advisories?query=shai-hulud