Syft SBOM 生成器
概览
Syft 是一个 CLI 工具和 Go 库,用于从容器镜像和文件系统中生成全面的软件物料清单(SBOM)。它提供了对 28+ 生态系统中的包和依赖项的可见性,支持多种 SBOM 格式(CycloneDX, SPDX)用于漏洞管理、许可证合规性和供应链安全。
支持的生态系统
语言 & 包管理器: Alpine (apk), C/C++ (conan), Dart (pub), Debian/Ubuntu (dpkg), Dotnet (deps.json), Go (go.mod), Java (JAR/WAR/EAR/Maven/Gradle), JavaScript (npm/yarn), PHP (composer), Python (pip/poetry/setup.py), Red Hat (RPM), Ruby (gem), Rust (cargo), Swift (cocoapods)
容器 & 系统: OCI 镜像,Docker 镜像,Singularity,容器层,Linux 发行版
快速开始
为容器镜像生成 SBOM:
# 使用 Docker
docker run --rm -v $(pwd):/out anchore/syft:latest <image> -o cyclonedx-json=/out/sbom.json
# 本地安装
syft <image> -o cyclonedx-json=sbom.json
# 示例
syft alpine:latest -o cyclonedx-json
syft docker.io/nginx:latest -o spdx-json
syft dir:/path/to/project -o cyclonedx-json
核心工作流程
工作流程 1:容器镜像 SBOM 生成
创建容器镜像的 SBOM:
- 确定目标容器镜像(本地或注册表)
- 运行 Syft 生成 SBOM:
syft <image-name:tag> -o cyclonedx-json=sbom-cyclonedx.json - 可选生成多种格式:
syft <image-name:tag> \ -o cyclonedx-json=sbom-cyclonedx.json \ -o spdx-json=sbom-spdx.json \ -o syft-json=sbom-syft.json - 将 SBOM 工件与镜像一起存储以进行追溯
- 使用 SBOM 进行漏洞扫描,使用 Grype 或其他工具
- 跟踪 SBOM 版本与镜像发布
工作流程 2:CI/CD 流水线集成
进度: [ ] 1. 在镜像创建后将 Syft 添加到构建流水线 [ ] 2. 生成标准格式(CycloneDX 或 SPDX)的 SBOM [ ] 3. 将 SBOM 存储为构建工件 [ ] 4. 扫描 SBOM 以查找漏洞(使用 Grype 或类似工具) [ ] 5. 在关键漏洞或许可证违规时失败构建 [ ] 6. 与容器镜像一起发布 SBOM [ ] 7. 与漏洞管理平台集成
系统地完成每个步骤。完成的项目打勾。
工作流程 3:文件系统和应用程序扫描
从源代码或文件系统生成 SBOM:
- 导航到项目根目录或指定路径
- 扫描目录结构:
syft dir:/path/to/project -o cyclonedx-json=app-sbom.json - 审查检测到的包和依赖项
- 验证包检测的准确性(检查误报/漏报)
- 如有需要配置排除项(使用
.syft.yaml) - 为每个发布版本生成 SBOM
- 跟踪版本间依赖项的变化
工作流程 4:SBOM 分析和漏洞扫描
将 SBOM 生成与漏洞评估结合起来:
- 使用 Syft 生成 SBOM:
syft <target> -o cyclonedx-json=sbom.json - 使用 Grype 扫描 SBOM 中的漏洞:
grype sbom:sbom.json -o json --file vulnerabilities.json - 按严重程度审查漏洞发现
- 按可利用性和修复可用性过滤
- 根据以下内容优先修复:
- CVSS 评分
- 活跃利用状态
- 修复可用性
- 依赖深度
- 更新依赖项并重新生成 SBOM
- 重新扫描以验证漏洞修复
工作流程 5:签名 SBOM 证明
创建加密签名的 SBOM 证明:
- 安装 cosign(用于签名):
# macOS brew install cosign # Linux wget https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64 chmod +x cosign-linux-amd64 mv cosign-linux-amd64 /usr/local/bin/cosign - 生成 SBOM:
syft <image> -o cyclonedx-json=sbom.json - 创建证明并签名:
cosign attest --predicate sbom.json --type cyclonedx <image> - 验证证明:
cosign verify-attestation --type cyclonedx <image> - 将签名与 SBOM 一起存储以进行出处验证
输出格式
Syft 支持多种 SBOM 格式以适应不同用例:
| 格式 | 用例 | 规范 |
|---|---|---|
cyclonedx-json |
现代 SBOM 标准,广泛的工具支持 | CycloneDX 1.4+ |
cyclonedx-xml |
CycloneDX XML 变体 | CycloneDX 1.4+ |
spdx-json |
Linux 基金会标准 | SPDX 2.3 |
spdx-tag-value |
SPDX 文本格式 | SPDX 2.3 |
syft-json |
Syft 原生格式(最详细) | Syft-specific |
syft-text |
人类可读的控制台输出 | Syft-specific |
github-json |
GitHub 依赖项提交 | GitHub-specific |
template |
自定义 Go 模板输出 | 用户定义 |
使用 -o 标志指定:
syft <target> -o cyclonedx-json=output.json
配置
在项目根目录或主目录中创建 .syft.yaml:
# Cataloger 配置
package:
cataloger:
enabled: true
scope: all-layers # 选项:all-layers, squashed
search:
unindexed-archives: false
indexed-archives: true
# 排除
exclude:
- "**/test/**"
- "**/node_modules/**"
- "**/.git/**"
# 注册表认证
registry:
insecure-skip-tls-verify: false
auth:
- authority: registry.example.com
username: user
password: pass
# 输出格式默认值
output: cyclonedx-json
# 日志级别
log:
level: warn # 选项:error, warn, info, debug, trace
常见模式
模式 1:多架构镜像扫描
扫描多平台镜像的所有架构:
# 扫描特定架构
syft --platform linux/amd64 <image> -o cyclonedx-json=sbom-amd64.json
syft --platform linux/arm64 <image> -o cyclonedx-json=sbom-arm64.json
# 或扫描清单列表(所有架构)
syft <image> --platform all -o cyclonedx-json
模式 2:私有注册表认证
从私有注册表访问镜像:
# 使用 Docker 凭据
docker login registry.example.com
syft registry.example.com/private/image:tag -o cyclonedx-json
# 使用环境变量
export SYFT_REGISTRY_AUTH_AUTHORITY=registry.example.com
export SYFT_REGISTRY_AUTH_USERNAME=user
export SYFT_REGISTRY_AUTH_PASSWORD=pass
syft registry.example.com/private/image:tag -o cyclonedx-json
# 使用配置文件(推荐)
# 将凭据添加到 .syft.yaml
模式 3:OCI 归档扫描
扫描保存的容器镜像(OCI 或 Docker 格式):
# 保存镜像到归档
docker save nginx:latest -o nginx.tar
# 扫描归档
syft oci-archive:nginx.tar -o cyclonedx-json=sbom.json
# 或扫描 Docker 归档
syft docker-archive:nginx.tar -o cyclonedx-json=sbom.json
模式 4:比较不同版本之间的 SBOM
跟踪发布间依赖项的变化:
# 为两个版本生成 SBOM
syft myapp:v1.0 -o syft-json=sbom-v1.0.json
syft myapp:v2.0 -o syft-json=sbom-v2.0.json
# 使用 jq 比较
jq -s '{"added": (.[1].artifacts - .[0].artifacts), "removed": (.[0].artifacts - .[1].artifacts)}' \
sbom-v1.0.json sbom-v2.0.json
模式 5:过滤 SBOM 输出
提取特定包信息:
# 生成详细的 SBOM
syft <target> -o syft-json=full-sbom.json
# 提取仅 Python 包
cat full-sbom.json | jq '.artifacts[] | select(.type == "python")'
# 提取具有特定许可证的包
cat full-sbom.json | jq '.artifacts[] | select(.licenses[].value == "MIT")'
# 按生态系统计算包数量
cat full-sbom.json | jq '.artifacts | group_by(.type) | map({type: .[0].type, count: length})'
安全考虑
- 敏感数据处理:SBOM 可能包含内部包名称和版本。安全地存储 SBOM 并限制授权人员访问
- 访问控制:将 SBOM 生成和访问限制在构建系统。使用只读凭据进行注册表访问
- 审计日志:记录 SBOM 生成事件、分发和访问以进行合规性跟踪
- 合规性:SBOM 支持符合行政命令 14028(软件供应链安全)、NIST 指南和 OWASP 建议
- 安全默认值:使用签名证明为生产 SBOM 确保完整性和出处
集成点
CI/CD 集成
GitHub Actions:
- name: 使用 Syft 生成 SBOM
uses: anchore/sbom-action@v0
with:
image: ${{ env.IMAGE_NAME }}:${{ github.sha }}
format: cyclonedx-json
output-file: sbom.json
- name: 上传 SBOM
uses: actions/upload-artifact@v3
with:
name: sbom
path: sbom.json
GitLab CI:
sbom-generation:
image: anchore/syft:latest
script:
- syft $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA -o cyclonedx-json=sbom.json
artifacts:
reports:
cyclonedx: sbom.json
Jenkins:
stage('Generate SBOM') {
steps {
sh 'syft ${IMAGE_NAME}:${BUILD_NUMBER} -o cyclonedx-json=sbom.json'
archiveArtifacts artifacts: 'sbom.json'
}
}
漏洞扫描
与 Grype 集成进行漏洞扫描:
# 生成 SBOM 并扫描在一个流水线中
syft <target> -o cyclonedx-json=sbom.json
grype sbom:sbom.json
SBOM 分发
将 SBOM 附加到容器镜像:
# 使用 ORAS
oras attach <image> --artifact-type application/vnd.cyclonedx+json sbom.json
# 使用 Docker 清单
# 将 SBOM 存储为附加层或单独工件
高级使用
自定义模板输出
使用 Go 模板创建自定义输出格式:
# 创建模板文件
cat > custom-template.tmpl <<'EOF'
{{- range .Artifacts}}
{{.Name}}@{{.Version}} ({{.Type}})
{{- end}}
EOF
# 使用模板
syft <target> -o template -t custom-template.tmpl
扫描特定层
分析容器镜像中的特定层:
# 压缩视图(默认 - 最终文件系统状态)
syft <image> --scope squashed -o cyclonedx-json
# 所有层(每层的包)
syft <image> --scope all-layers -o cyclonedx-json
环境变量配置
通过环境变量配置 Syft:
export SYFT_SCOPE=all-layers
export SYFT_OUTPUT=cyclonedx-json
export SYFT_LOG_LEVEL=debug
export SYFT_EXCLUDE="**/test/**,**/node_modules/**"
syft <target>
故障排除
问题:SBOM 中缺少包
解决方案:启用所有层范围或检查包管理器文件:
syft <target> --scope all-layers -o syft-json
验证包清单文件是否存在(package.json, requirements.txt, go.mod 等)
问题:注册表认证失败
解决方案:确保 Docker 凭据已配置或使用显式认证:
docker login <registry>
# 然后运行 syft
syft <registry>/<image> -o cyclonedx-json
问题:SBOM 尺寸过大
解决方案:使用压缩范围并排除测试/开发依赖项:
# 在 .syft.yaml 中
package:
cataloger:
scope: squashed
exclude:
- "**/test/**"
- "**/node_modules/**"
- "**/.git/**"
问题:扫描性能慢
解决方案:禁用未索引归档扫描以获得更快的结果:
# 在 .syft.yaml 中
package:
search:
unindexed-archives: false
许可证合规性
从 SBOM 中提取许可证信息:
# 生成 SBOM
syft <target> -o syft-json=sbom.json
# 提取唯一许可证
cat sbom.json | jq -r '.artifacts[].licenses[].value' | sort -u
# 查找具有特定许可证的包
cat sbom.json | jq '.artifacts[] | select(.licenses[].value | contains("GPL"))'
# 生成许可证报告
cat sbom.json | jq -r '.artifacts[] | "\(.name):\(.licenses[].value)"' | sort
漏洞管理工作流程
完整的工作流程,将 SBOM 生成与漏洞管理集成:
进度: [ ] 1. 为应用程序/容器生成 SBOM [ ] 2. 扫描 SBOM 以查找已知漏洞 [ ] 3. 按严重程度和可利用性分类漏洞 [ ] 4. 检查可用的补丁和更新 [ ] 5. 更新有漏洞的依赖项 [ ] 6. 更新后重新生成 SBOM [ ] 7. 重新扫描以确认漏洞修复 [ ] 8. 记录不可修复漏洞的接受风险 [ ] 9. 安排定期 SBOM 再生和扫描
系统地完成每个步骤。完成的项目打勾。