vadimpiven/node-addon-slsa
GitHub: vadimpiven/node-addon-slsa
为包含预构建原生 addon 的 npm 包提供端到端供应链来源验证,确保包体与二进制文件同源可信。
Stars: 0 | Forks: 0
[][status-dashboard]
[][coverage-dashboard]
# node-addon-slsa
针对包含预构建原生 addon 的 npm 包的供应链来源验证。
确保 npm 包及其预构建二进制文件均由同一 GitHub Actions 工作流运行生成,使用 [sigstore] 和 [GitHub Attestations API][gh-attestations]。如果任何验证步骤失败,安装将中止并报 `SECURITY` 错误。
## 端到端示例
### 1. 配置你的包
```
{
"name": "my-native-addon",
"version": "1.0.0",
"repository": {
"url": "git+https://github.com/owner/repo.git"
},
"type": "module",
"exports": {
".": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
"./package.json": "./package.json"
},
"addon": {
"path": "./dist/my_addon.node",
"url": "https://github.com/owner/repo/releases/download/v{version}/my_addon-v{version}-{platform}-{arch}.node.gz"
},
"scripts": {
"postinstall": "slsa wget",
"pack-addon": "slsa pack"
},
"dependencies": {
"node-addon-slsa": "^1.0.0"
}
}
```
- **`exports`** — 必须包含 `"./package.json"` 入口,
这样你的代码才能通过 `import pkg from "./package.json"` 在运行时读取 `addon.path`;
若无此项,Node.js 的严格 ESM exports 解析将阻止访问
- **`addon.path`** — 原生二进制文件的安装位置,
相对于包根目录
- **`addon.url`** — 下载 URL 模板;
支持 `{version}`, `{platform}`, `{arch}` 占位符
- **`postinstall`** — 在 `npm install` 时运行 `slsa wget`:
下载二进制文件,验证来源,并安装
- **`pack-addon`** — 在 CI 中运行 `slsa pack`:
在上传到 GitHub release 前 gzip 压缩二进制文件
### 2. 在 CI 中构建并发布
```
jobs:
build:
runs-on: ubuntu-latest
permissions:
id-token: write # OIDC token for sigstore
contents: write # gh release upload
attestations: write
steps:
- uses: actions/checkout@v6
- run: npm run build
- name: Compress binary for release
run: npx slsa pack
- name: Attest binary provenance
uses: actions/attest-build-provenance@v4
with:
subject-path: dist/my_addon-v*.node.gz
- name: Upload binary to release
run: gh release upload "$TAG" dist/my_addon-v*.node.gz
publish:
needs: build
runs-on: ubuntu-latest
permissions:
id-token: write # npm provenance
steps:
- run: npm publish --provenance --access public
```
### 3. 执行 `npm install` 时
`slsa wget` postinstall hook 会自动运行:
1. 通过 sigstore 验证 npm 包来源
2. 从 Fulcio 证书中提取 GitHub Actions Run Invocation URI
3. 从 GitHub release 下载压缩的二进制文件
4. 验证二进制文件的证明 (attestation) 与同一工作流运行相匹配
5. 解压并安装二进制文件
### 4. 加载原生 addon
使用 `package.json` 中的 `addon.path` 来定位
已下载的二进制文件:
```
import { createRequire } from "node:module";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import packageJson from "../package.json" with { type: "json" };
const require = createRequire(import.meta.url);
const root = join(dirname(fileURLToPath(import.meta.url)), "..");
const addon = require(join(root, packageJson.addon.path));
```
这也是为什么必须导出 `"./package.json"` —
它允许在严格的 ESM exports 下解析 JSON 导入。
## 详情
### `repository` 字段
`repository` 字段(或 `repository.url`)决定了
用于证明验证的预期 GitHub 仓库。
两个 CLI 命令都会从工作目录的 `package.json` 中读取它。
### CLI
| 命令 / 选项 | 用途 |
| ------------------------ | -------------------------------------- |
| `slsa pack` | Gzip 压缩原生二进制文件以供发布 |
| `slsa wget` | 下载、验证并安装原生二进制文件 |
| `slsa wget --no-verify` | 不进行来源验证直接下载 |
| `slsa --help`, `slsa -h` | 显示用法信息 |
### 验证链
sigstore 验证会校验完整的 Fulcio CA 链、
日志包含证明、Signed Entry Timestamp
(SET) 以及 Signed Certificate Timestamps (SCTs)。二进制
验证随后确认 GitHub 证明是在与 npm 包同一工作流运行中签署的,从而将两个构建产物链接到同一个可审计的构建中。
| 威胁 | 缓解措施 |
| ----------------------- | ------------------------------------ |
| 被篡改的 npm 包 | sigstore 来源验证 |
| 被篡改的 GitHub release | GitHub Attestations API + sigstore |
| 不匹配的构建产物 | 通过 URI 检查是否为同一工作流运行 |
### 开发模式
版本 `0.0.0` 会跳过所有验证,允许在没有已发布证明的情况下进行本地
开发和 CI 测试。
### 要求
- Node.js `^20.19.0 || >=22.12.0` 以支持 ESM
- npm 包需使用 [`--provenance`][npm-provenance] 发布
- 二进制文件需使用 [`actions/attest-build-provenance`][attest-action] 进行证明
标签:CI/CD安全, DevSecOps, GitHub Actions, GitHub Attestations, JSONLines, Llama, MITM代理, Node.js原生插件, NPM包, OSV-Scalibr, SBOM, Sigstore, SLSA, 上游代理, 二进制安全, 代码签名, 安装钩子, 完整性校验, 数据管道, 文档安全, 暗色界面, 来源验证, 硬件无关, 自动化攻击, 自动化攻击, 自动笔记, 跌倒检测, 软件工程, 软件开发工具包, 软件物料清单, 零信任