leagames0221-sys/sbom-pilot

GitHub: leagames0221-sys/sbom-pilot

一个面向独立开发者和小型团队的零成本离线命令行工具,用于生成软件物料清单(SBOM)、执行漏洞扫描并输出多国供应链合规报告。

Stars: 0 | Forks: 0

# sbom-pilot **白话摘要** *(面向非专业读者)* - **SBOM (Software Bill of Materials)** —— 一份机器可读的列表,记录了一款软件引入的所有库(包括直接和间接/传递依赖)。可以将其理解为软件的“成分表”。 - **漏洞扫描** —— 将上述成分表与公开的已知安全漏洞数据库(OSV / NVD / GHSA)进行交叉比对。 - **合规报告** —— 将 SBOM 和扫描输出结果重新整理为特定法规要求的格式(例如日本 APPI 26-2 泄露报告、基于 EO 14028 的美国联邦采购要求、欧盟 CRA 合规性等)。 - **为何重要** —— 供应链监管法规现在同样适用于小型团队,但企业级的 SCA 平台定价是按照企业预算设定的。`sbom-pilot` 能够基于免费 / 本地的技术栈生成相同的交付物。 [![ci](https://static.pigsec.cn/wp-content/uploads/repos/cas/99/993938d8ce5e902ccfb9d6747725c320d855dea3235ed9a304cedf0d94c9321f.svg)](https://github.com/leagames0221-sys/sbom-pilot/actions/workflows/ci.yml) [![OpenSSF Scorecard](https://github.com/leagames0221-sys/sbom-pilot/actions/workflows/scorecard.yml/badge.svg)](https://github.com/leagames0221-sys/sbom-pilot/actions/workflows/scorecard.yml) [![CodeQL](https://static.pigsec.cn/wp-content/uploads/repos/cas/53/539e9a6bf48ad24469a4363bff3aa68124154549e26592783d3d8577f2acbbfc.svg)](https://github.com/leagames0221-sys/sbom-pilot/actions/workflows/codeql.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) [![Constraint: zero credit card](https://img.shields.io/badge/Constraint-zero%20credit%20card-blue)](#selected-under) [![Constraint: local LLM (default)](https://img.shields.io/badge/Constraint-local%20LLM%20%28default%29-blue)](#selected-under) [![Constraint: free / OSS only](https://img.shields.io/badge/Constraint-free%20%2F%20OSS%20only-blue)](#selected-under) [![Constraint: security defense-in-depth](https://img.shields.io/badge/Constraint-security%20defense--in--depth-blue)](#selected-under) ## 入选标准 本仓库专门展示:防御优先的 SBOM CLI,具备 `付费 API 6 层防御`(构造器拦截 + 预检储备 + 密钥防泄露 + CI 自动调用禁用 + 默认 mock + 仅限零信用卡服务),默认使用 Ollama 的 `suggest` 提供商并带有 mock 回退,以及基于 OSV 缓存快照的离线优先漏洞扫描。有关字面上的 6 层防御规范,请参阅 [docs/PROVIDERS.md](docs/PROVIDERS.md)。 ## 1. 问题背景 供应链安全现在已成为法规要求,而不仅仅是最佳实践: - **日本**:改正個人情報保護法 26-2(2022 年生效)强制要求进行事件分类报告,在实际操作中,这要求提供发生泄露的系统的带版本号的组件清单。经济产业省(METI)的 SBOM 導入手引き v2.0(2024-08)为该清单设定了最低字段基准。 - **美国**:NTIA 最低要素(根据第 14028 号行政命令 EO 14028)定义了联邦采购中 SBOM 必须包含的内容。 - **欧盟**:网络弹性法案(CRA,附录 I)将类似义务扩展到了在欧盟境内销售的“带有数字元素的产品”,并将分阶段执行至 2027 年。 企业安全团队有预算购买付费的 SCA 平台。个人开发者和小型企业则没有——但法律义务却同等适用。`sbom-pilot` 的存在就是为了通过一个零成本的 CLI 来填补这一空白。 ## 2. 快速开始 这是一个阶段 α 的 PoC。该包**尚未发布到 npm registry** —— 阶段 α 需通过本地克隆运行。`npm install -g` 路径将在阶段 α 公开切换 + 首个 `v0.1.0` 标签发布后激活。 ``` # 从本地 checkout 运行(当前 Phase α 路径): git clone https://github.com/leagames0221-sys/sbom-pilot.git cd sbom-pilot pnpm install --frozen-lockfile pnpm build # compiles src/ → dist/ node dist/cli/index.js --help # or: pnpm exec tsx bin/sbom-pilot.ts --help ``` 阶段 α 公开切换 + npm 发布后: ``` # npm install -g sbom-pilot # ← Phase α 标记 v0.1.0 后可用 # sbom-pilot --help ``` 子命令示例(通过解析后的二进制文件调用,下文简称为 `sbom-pilot`): ``` # 从项目目录生成 SPDX 2.3 SBOM sbom-pilot sbom ./my-project --format spdx > sbom.spdx.json # 扫描项目以查找已知漏洞(离线 DB) sbom-pilot scan ./my-project --output findings.sarif --fail-on critical,high # 生成 Japan APPI 26-2 合规报告 sbom-pilot report ./my-project --standard appi-26-2 > report.txt # 获取针对特定 advisory 的升级建议(Ollama-default) sbom-pilot suggest GHSA-1234-5678-90ab ``` 没有任何标志需要 API 密钥。没有任何子命令会写入凭据。默认情况下,`scan` 在零网络出口的情况下运行。`--refresh` 标志预留给即将推出的漏洞数据库刷新脚本(T-29/T-30);在当前阶段 α 构建中,它是一个无操作,仅发出 stderr 警告并继续使用现有缓存。在刷新配置落地之前,请手动填充 / 更新缓存。 ### 演示输出 上述四个子命令针对 `tests/fixtures/projects/npm-tiny`(合成的 6 包 npm 项目,无真实依赖)产生以下终端输出。由 `docs/demo/cli/render.py`(Pillow + MS Gothic,无网络出口)从原始 stdout/stderr 渲染。 | 命令 | 截图 | |---|---| | `sbom-pilot --help` | [help.png](docs/demo/cli/help.png) | | `sbom-pilot sbom --format spdx` | [sbom.png](docs/demo/cli/sbom.png) | | `sbom-pilot scan --vuln-db ` | [scan.png](docs/demo/cli/scan.png) | | `sbom-pilot report --standard appi-26-2` | [report.png](docs/demo/cli/report.png) | 上面的 `scan` 输出显示了针对由 `tests/fixtures/vuln-db-seed/vuln-db.json` 播种的 npm-tiny fixture 的 3 个合成发现(1 个 HIGH lodash + 1 个 MODERATE express + 1 个 LOW underscore)。`report` 的输出为日语,因为 `appi-26-2`(個人情報保護法 第26条の2)是一项日本法规;可通过 `--standard ntia` / `eu-cra` / `meti-sbom-v2` 获取英文报告。 要在本地重新生成屏幕截图: ``` # 捕获原始输出(Bash 重定向;PowerShell 用户:通过 Set-Content -Encoding utf8 进行管道操作) NO_COLOR=1 pnpm exec tsx bin/sbom-pilot.ts --help > docs/demo/cli/help.txt 2>&1 NO_COLOR=1 pnpm exec tsx bin/sbom-pilot.ts sbom tests/fixtures/projects/npm-tiny --format spdx --no-color > docs/demo/cli/sbom.txt 2>&1 NO_COLOR=1 pnpm exec tsx bin/sbom-pilot.ts scan tests/fixtures/projects/npm-tiny --vuln-db tests/fixtures/vuln-db-seed/vuln-db.json --no-color > docs/demo/cli/scan.txt 2>&1 NO_COLOR=1 pnpm exec tsx bin/sbom-pilot.ts report tests/fixtures/projects/npm-tiny --standard appi-26-2 --vuln-db tests/fixtures/vuln-db-seed/vuln-db.json --no-color > docs/demo/cli/report.txt 2>&1 # 渲染 PNG(系统 Python >= 3.10 + Pillow) python docs/demo/cli/render.py ``` ## 3. 子命令 | 子命令 | 用途 | 默认输出 | 退出策略 | |---|---|---|---| | `sbom ` | 从 npm / pnpm / pip / go.mod 清单生成 SPDX 2.3 或 CycloneDX 1.5 | stdout(或 `--output ` 原子写入) | 成功返回 `EX_OK`,清单检测失败返回 `EX_DATAERR` | | `scan ` | 与离线 OSV 缓存关联,生成 SARIF 2.1.0 + stderr 摘要 | stdout SARIF + stderr 表格 | 除非匹配到 `--fail-on ` 的发现,否则返回 `EX_OK` | | `report ` | 生成按法规划分的合规报告(appi-26-2 / meti-sbom-v2 / ntia / eu-cra) | stdout 文本 | 缺少 `--standard` 则返回 `EX_USAGE` | | `suggest ` | 通过本地 LLM 提供自由文本的升级建议(默认 Ollama,回退到 mock) | stdout 文本 | 成功返回 `EX_OK`,提供商配置错误返回 `EX_TEMPFAIL` | 所有子命令均提供 `--help` 列表。请尝试 `sbom-pilot --help`。 全局标志:`--no-color` 去除 stdout/stderr 中的 ANSI 转义字符;`-q` / `--quiet` 抑制信息性的 stderr(错误仍会显示);`-V` / `--version` 打印版本字符串。 ## 4. 架构 5 层单向依赖方向(根据 ADR-0006): ``` ┌─────────────────────────────────────────────────────────┐ │ Layer 5 — CLI │ │ src/cli/ + bin/sbom-pilot.ts │ │ commander setup, exit codes, --help, did-you-mean, │ │ --version, output sanitization │ ├─────────────────────────────────────────────────────────┤ │ Layer 4 — Emitters │ │ src/emitters/ │ │ spdx-2.3.ts / cyclonedx-1.5.ts / sarif-2.1.0.ts │ │ compliance/{appi-26-2,meti-sbom-v2,ntia,eu-cra}.ts │ ├─────────────────────────────────────────────────────────┤ │ Layer 3 — Scanners │ │ src/scanners/ │ │ vuln-db.ts / correlator.ts / severity.ts │ ├─────────────────────────────────────────────────────────┤ │ Layer 2 — IR (intermediate representation) │ │ src/ir/ │ │ sbom-ir.ts / schemas.ts (zod) / severity.ts (vocab) │ ├─────────────────────────────────────────────────────────┤ │ Layer 1 — Parsers │ │ src/parsers/ │ │ npm.ts / pnpm.ts / pip.ts / go-mod.ts │ └─────────────────────────────────────────────────────────┘ Side modules: src/providers/llm/ — Ollama, mock, paid-API defense stub src/schemas/ — vendored SPDX / CycloneDX / SARIF JSON schemas src/util/ — atomic write, ANSI strip, credential scrub src/exit-codes.ts — sysexits enum ``` **方向**:CLI → Emitters → IR ← Scanners ← Parsers。五条字面上的禁止边(Parsers→Emitters, Scanners→Parsers, IR→anything, Emitters→Scanners, anything→CLI)通过 `dependency-cruiser` (`.dependency-cruiser.cjs`) 进行 CI 拦截。有关完整原理,请参阅 [`docs/adr/0006-module-boundary.md`](docs/adr/0006-module-boundary.md)。 ### 技术栈(字面锁定,根据 ADR-0002) | 层级 | 选择 | 原因 | |---|---|---| | 语言 | TypeScript (strict + `exactOptionalPropertyTypes`) | 同级可复用模式;zod + ajv 生态系统成熟度 | | 运行时 | Node.js 20 LTS | LTS 支持至 2026-04;强制执行 `engines.node` | | 包管理器 | pnpm 10 | 提交 Lockfile,在 CI 中使用 `--frozen-lockfile`,工作流中加入审计拦截 | | 测试框架 | vitest 3 | 原生 ESM,TS 一等公民,内置快照 | | CLI 解析器 | commander 13 | 成熟,MIT 许可,兼容 sysexits 的退出覆盖 | | Schema 验证 | ajv 8 + ajv-formats | 符合 RFC 的 JSON schema 2020-12 + 格式验证器 | | 运行时验证 | zod 3 | 用于 IR 形状拦截的类型收窄解析器 | ## 5. 合规支持 有四个一级支持报告,每个报告都带有 golden fixtures 和适用的 SARIF 拦截: | 标准 | 输出语言 | AC-ID | 参考 | |---|---|---|---| | 改正個情法 第26条の2 | 日语 | AC-003-1 + AC-003-7 | 個人情報保護委員会 ガイドライン | | METI ソフトウェア管理に向けた SBOM 導入手引き v2.0 | 日语 | AC-003-2 | METI 2024-08 出版物 | | NTIA Minimum Elements | 英语 | AC-003-3 | U.S. EO 14028 / NTIA 2021 | | EU Cyber Resilience Act Annex I | 英语 | AC-003-4 | Regulation (EU) 2024/2847 | 每个合规发射器(emitter)都可以独立测试;`tests/golden/compliance/` 语料库锁定了输出结构,因此监管漂移会在 PR 审查时被发现,而不是在审计时。 ## 6. 付费 API + 供应链防御 该项目围绕四项代码级防御和两项架构约束构建(根据 ADR-0002 §“接受的权衡” + spec.md §10.5 AC-NF-1..6,与 [src/providers/llm/paid-defense.ts](src/providers/llm/paid-defense.ts) 中的内联注释相匹配): 1. **构造器拦截** —— 只有当 `_API_KEY` *和* `SBOM_PILOT_LLM_PROVIDER=` 同时存在于环境中时,才能实例化付费 LLM 提供商。缺少任何一个都会拒绝构造。 2. **预检储备** —— 三个上限(token / 请求 / 美元成本)加上一个中毒状态标志可阻止静默失控。 3. **密钥防泄露** —— 错误消息会将 API 密钥掩盖为前 6 个字符;堆栈跟踪转储永远不会暴露该密钥。 4. **CI 自动调用禁用** —— 在 `CI=true` 或任何 `*_TEST_*` 环境下,全局 `fetch` 会被捕获,并在第一次未打桩的调用时抛出异常。回归测试(`tests/regression/paid-api-blocking.test.ts`)确保这一机制保持有效。 5. **默认提供商 = mock** —— 当未配置 LLM 时,每个子命令入口点都会回退到 mock 提供商,因此 CLI 默认可以在离线状态下工作。 6. **无需信用卡** —— 每个依赖项(运行时 + CI + LLM)都有文档记录的、足够该项目使用的免费层级。代码库中的任何路径都不会在未经用户明确选择的情况下读取付费服务。 供应链规范补充: - 在 CI(3 种操作系统矩阵)中使用 `pnpm install --frozen-lockfile`。 - `pnpm audit --audit-level=high` 作为 CI 拦截。 - `dependency-cruiser` 检查 5 条禁止的架构边缘。 - 接入了 OpenSSF Scorecard + CodeQL + Dependabot(公开切换后会自动将 SARIF 发布到 Security 标签页)。 - Pre-commit hook (`scripts/check_forbidden_tokens.py`) 在提交前阻止 channel-B 掩蔽列表。 ## 7. 安全性 有关协调披露策略和支持的版本表,请参阅 [`SECURITY.md`](SECURITY.md)。 运营强化: - **原子写入** —— 每个发射器都通过 `atomicWrite()`(临时重命名模式)进行写入。进程在写入过程中被终止不会在磁盘上留下任何不完整的文件。 - **凭据清理** —— `src/util/credential-scrub.ts` 在发射器边界处掩盖 `Bearer …`, `AWS_…`, `*_KEY=…`, `password=…` 模式。直接吸取自 CVE-2025-65965 (grype GHSA-6gxw-85q2-q646 注册表凭据泄露) 的教训;参见 [`NOTICE`](
标签:AI风险缓解, LLM防护, MITM代理, SBOM, 人工智能安全, 合规性, 硬件无关, 自动化攻击