SBOM 与供应链透明
本页提供:syft 生成 SBOM 的完整命令(JSON 与 SPDX 两种格式)、syft + grype 漏洞扫描完整命令链、SPDX 格式最小示例(含必要字段)、GitHub Actions 中集成 SBOM 生成与存储的配置,以及供应链攻击 3 种典型模式与对应防御措施。
SBOM 的价值在于可比对、可自动化:同一坐标在不同工具间应指向同一逻辑组件。SKILL 需写清生成命令、schema 版本、与容器层/传递依赖的合并策略,以及制品库保留周期与访问控制。
syft 生成 SBOM 命令与 grype 漏洞扫描
syft 生成 SBOM(JSON 与 SPDX 两种格式)
# 安装 syft
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
# 从当前目录生成 CycloneDX JSON SBOM
syft dir:. \
--output cyclonedx-json=sbom-cyclonedx.json \
--name myapp \
--version $(git rev-parse --short HEAD)
# 生成 SPDX JSON 格式
syft dir:. \
--output spdx-json=sbom-spdx.json
# 从容器镜像生成(包含基础层)
syft myapp:latest \
--output cyclonedx-json=sbom-image.json \
--scope all-layers
# syft + grype 漏洞扫描完整命令链
syft myapp:latest -o json > /tmp/sbom.json
grype sbom:/tmp/sbom.json \
--fail-on high \
--output json \
> grype-report.json
# 查看 Critical/High 漏洞摘要
grype sbom:/tmp/sbom.json \
--fail-on high \
--output table | head -40
- 发布物附带校验和与可选数字签名;内部 fork 与补丁版本在 SBOM 中显式标注来源。
- 与依赖升级、CVE 工单联动,形成「发现 → 评估 → 修复 → 再扫描」闭环。
- 监管或客户审计场景下,SBOM 应能与构建 provenance(如 SLSA、in-toto)交叉验证到具体 commit 与流水线 run。
SPDX 格式最小示例与 GitHub Actions 集成
SPDX JSON 格式最小示例(展示必要字段)
{
"spdxVersion": "SPDX-2.3",
"dataLicense": "CC0-1.0",
"SPDXID": "SPDXRef-DOCUMENT",
"name": "myapp-sbom",
"documentNamespace": "https://example.com/sbom/myapp-abc1234",
"documentDescribes": ["SPDXRef-Package-myapp"],
"packages": [
{
"SPDXID": "SPDXRef-Package-myapp",
"name": "myapp",
"versionInfo": "1.2.3-abc1234",
"downloadLocation": "NOASSERTION",
"filesAnalyzed": false,
"licenseDeclared": "MIT",
"licenseConcluded": "MIT",
"copyrightText": "Copyright 2025 Example Corp"
},
{
"SPDXID": "SPDXRef-Package-express-4.18.2",
"name": "express",
"versionInfo": "4.18.2",
"downloadLocation": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
"filesAnalyzed": false,
"licenseDeclared": "MIT",
"licenseConcluded": "MIT",
"externalRefs": [
{"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "pkg:npm/express@4.18.2"}
]
}
],
"relationships": [
{"spdxElementId": "SPDXRef-DOCUMENT",
"relationshipType": "DESCRIBES",
"relatedSpdxElement": "SPDXRef-Package-myapp"},
{"spdxElementId": "SPDXRef-Package-myapp",
"relationshipType": "DEPENDS_ON",
"relatedSpdxElement": "SPDXRef-Package-express-4.18.2"}
]
}
GitHub Actions 中集成 SBOM 生成与存储
# .github/workflows/sbom.yml
name: SBOM Generation
on:
push:
branches: ["main"]
release:
types: [published]
jobs:
sbom:
runs-on: ubuntu-latest
permissions:
contents: write
id-token: write # for cosign OIDC signing
steps:
- uses: actions/checkout@v4
- name: Generate SBOM with syft
uses: anchore/sbom-action@v0
with:
path: .
format: spdx-json
output-file: sbom.spdx.json
artifact-name: sbom-${{ github.sha }}.spdx.json
- name: Scan SBOM with grype
uses: anchore/scan-action@v3
with:
sbom: sbom.spdx.json
fail-build: true
severity-cutoff: high
- name: Upload SBOM as release asset
if: github.event_name == 'release'
uses: actions/upload-release-asset@v1
with:
upload_url: ${{ github.event.release.upload_url }}
asset_path: sbom.spdx.json
asset_name: sbom-${{ github.event.release.tag_name }}.spdx.json
asset_content_type: application/json
选型提示:SPDX 描述许可证与版权;CycloneDX 承载漏洞扩展(VEX)。二者可并存,但需在 CI 中钉死 schema 版本与工具版本,避免字段漂移。
供应链攻击 3 种典型模式与防御
供应链攻击的 3 种典型模式与对应防御措施:
-
① 依赖投毒(Dependency Confusion):攻击者在公共 registry 发布与内部私有包同名的恶意包,npm/pip 在解析时优先安装公共版本。
防御:使用私有 registry 并在.npmrc/pip.conf中固定 scope 映射;对所有包配置 integrity hash(lockfile);在 SBOM 中验证 PURL 是否来自预期 registry。 -
② 构建系统入侵(SolarWinds 型):攻击者渗透 CI/CD 系统,在构建产物中注入恶意代码,但源码仓库不含恶意内容。
防御:实施 SLSA Level 3 provenance(构建在受控环境,产出带签名的 attestation);SBOM 需包含构建环境 hash,与镜像 digest 绑定;使用 Sigstore/cosign 签名。 -
③ 恶意维护者(XZ Utils 型):攻击者长期参与合法开源项目,获得维护权后注入后门。
防御:Pin 依赖到精确 commit hash(而非版本标签);定期 diff 关键依赖的 changelog;使用 Renovate/Dependabot 自动 PR 并配合 SBOM diff 审查;对供应商库变更触发自动漏洞扫描。
# .npmrc — 防止 Dependency Confusion
@mycompany:registry=https://npm.mycompany.internal
registry=https://registry.npmjs.org
# 固定依赖到 git commit hash(package.json)
"critical-lib": "github:org/critical-lib#a1b2c3d4e5f6..."
# cosign 签名镜像并附加 SBOM attestation
cosign sign --key cosign.key myapp:latest
cosign attest --predicate sbom.spdx.json \
--type spdxjson \
myapp:latest
SBOM 生命周期流程
建议固定顺序,避免在未锁定格式与版本的情况下先做漏洞对比,导致字段缺失或坐标无法匹配。
[ 锁定:SPDX / CycloneDX + schema + 生成工具版本 ]
│
▼
[ CI:语言锁文件 / 容器层 / 传递依赖 → 生成 SBOM 片段 ]
│
▼
[ 合并策略:去重键(PURL@version)、层顺序、补丁标注 ]
│
▼
[ 签名与存储:checksum、制品库 ACL、与镜像 digest 关联 ]
│
▼
[ 消费:CVE/VEX 扫描、许可证报表、与客户/监管交付物 ]
│
▼
[ 版本 diff:新增组件 / 许可变更 / 漏洞面变化摘要 ]
Package URL 坐标构建
Package URL(常写作 PURL)是跨生态的组件坐标:pkg:type/namespace/name@version。下方工具按常见类型做分段编码(简化实现,复杂 qualifiers 请查阅规范),便于在 SKILL 或工单中粘贴统一坐标。
SKILL 骨架
---
name: sbom-cn
description: 生成 SPDX/CycloneDX SBOM,用 syft+grype 扫描漏洞,签名存储,检查供应链攻击
---
# 步骤
1. 选定格式:SPDX(许可证合规)或 CycloneDX(漏洞 VEX);钉死 schema 版本与工具版本
2. 运行 syft 生成 SBOM:dir:. 或镜像,指定 --name 与 --version
3. 运行 grype 扫描:grype sbom:/tmp/sbom.json --fail-on high
4. GitHub Actions:sbom-action 生成 + scan-action 检查 + 上传 release asset
5. SBOM 字段校验:spdxVersion、SPDXID、documentNamespace、purl 均不为空
6. 与镜像 digest 关联:cosign attest --predicate sbom.json --type spdxjson
7. Dependency Confusion 防御:npmrc/pip.conf 固定 scope,lockfile 含 integrity hash
8. 构建系统入侵防御:SLSA Level 3,cosign 签名,provenance attestation
9. 维护者投毒防御:Pin 到 git commit hash;定期 diff 关键依赖
10. SBOM 版本 diff:对比上一版本的新增组件、许可证变更与漏洞面变化
11. 制品留存:SBOM 与镜像同级存储,检索键含产品名/版本/架构/构建号
12. 消费:CVE/VEX 扫描、许可证报表、与客户/监管交付物
# 禁止
- 禁止手工维护依赖列表(必须从 lockfile 自动生成)
- 禁止在 SBOM 中使用自定义非标准 SPDX ID