使用 CycloneDX 或 SPDX 格式生成软件物料清单 (SBOM),列出所有依赖项、许可证、漏洞及供应链元数据。
SBOM 生成器 : 创建一份综合软件材料法案,列出每一种依赖性、版本、许可证和已知弱点是一项面向实际任务的技能,主要用于支持 Rigu 所需的 CypromotDX 和 SPDX 格式。它将相关步骤、工具调用和结果整理方式集中到统一流程中,帮助使用者更快完成目标并减少重复操作。
实际使用前应先确认任务范围、数据来源、运行环境、必要权限和关键参数,再依据技能说明逐步执行;若输入条件不完整,应先补齐信息或采用保守配置,避免因错误假设导致结果偏离需求。
执行过程中需要关注工具调用是否成功、接口或依赖是否可用、输出格式是否符合预期,并对异常提示、缺失字段和边界情况进行处理;涉及批量任务时,还应保存进度,避免中断后重复操作。
生成一份全面的软件物料清单(Software Bill of Materials),完整列出所有依赖项、其版本号、许可证类型及已知漏洞。支持 CycloneDX 和 SPDX 格式,满足监管框架(FDA、欧盟《网络韧性法案》(Cyber Resilience Act)、NIST SSDF)的合规要求。
适用场景包括:“generate SBOM”、“software bill of materials”、“list all dependencies”、“license audit”、“supply chain inventory”、“compliance report”、“CycloneDX”、“SPDX”,或在安全/合规审计期间使用。
generate — 生成完整 SBOM扫描项目并输出完整的依赖项清单。
echo "=== 包管理器检测 ===" MANAGERS="" # Node.js [ -f "package-lock.json" ] && MANAGERS="$MANAGERS npm" && echo "✅ npm (package-lock.json)" [ -f "yarn.lock" ] && MANAGERS="$MANAGERS yarn" && echo "✅ Yarn (yarn.lock)" [ -f "pnpm-lock.yaml" ] && MANAGERS="$MANAGERS pnpm" && echo "✅ pnpm (pnpm-lock.yaml)" # Python [ -f "requirements.txt" ] && MANAGERS="$MANAGERS pip" && echo "✅ pip (requirements.txt)" [ -f "Pipfile.lock" ] && MANAGERS="$MANAGERS pipenv" && echo "✅ Pipenv (Pipfile.lock)" [ -f "poetry.lock" ] && MANAGERS="$MANAGERS poetry" && echo "✅ Poetry (poetry.lock)" [ -f "pdm.lock" ] && MANAGERS="$MANAGERS pdm" && echo "✅ PDM (pdm.lock)" # Go [ -f "go.sum" ] && MANAGERS="$MANAGERS go" && echo "✅ Go (go.sum)" # Rust [ -f "Cargo.lock" ] && MANAGERS="$MANAGERS cargo" && echo "✅ Cargo (Cargo.lock)" # Ruby [ -f "Gemfile.lock" ] && MANAGERS="$MANAGERS bundler" && echo "✅ Bundler (Gemfile.lock)" # PHP [ -f "composer.lock" ] && MANAGERS="$MANAGERS composer" && echo "✅ Composer (composer.lock)" # Java [ -f "pom.xml" ] && MANAGERS="$MANAGERS maven" && echo "✅ Maven (pom.xml)" [ -f "build.gradle" ] || [ -f "build.gradle.kts" ] && MANAGERS="$MANAGERS gradle" && echo "✅ Gradle" # .NET find . -name "*.csproj" -maxdepth 3 2>/dev/null | head -1 | grep -q . && MANAGERS="$MANAGERS nuget" && echo "✅ NuGet (.csproj)" echo "" echo "检测到的包管理器数量:$(echo $MANAGERS | wc -w)"
echo ""
echo "=== 依赖项提取 ==="
# npm/Node.js
if [ -f "package-lock.json" ]; then
echo "--- npm 依赖项 ---"
python3 -c "
import json
lock = json.load(open('package-lock.json'))
packages = lock.get('packages', {})
count = 0
for name, info in sorted(packages.items()):
if not name or name == '': continue
clean_name = name.replace('node_modules/', '')
version = info.get('version', '?')
license = info.get('license', 'UNKNOWN')
resolved = info.get('resolved', '')
dev = info.get('dev', False)
print(f'{clean_name}|{version}|{license}|{"dev" if dev else "prod"}')
count += 1
print(f'Total npm packages: {count}', file=__import__('sys').stderr)
" 2>/dev/null | head -50
fi
# Python
if [ -f "requirements.txt" ]; then
echo "--- Python 依赖项 ---"
python3 -c "
import re
with open('requirements.txt') as f:
for line in f:
line = line.strip()
if not line or line.startswith('#') or line.startswith('-'): continue
match = re.match(r'([a-zA-Z0-9_.-]+)s*([=<>!~]+s*S+)?', line)
if match:
name = match.group(1)
version = match.group(2) or 'any'
print(f'{name}|{version.strip()}|UNKNOWN|prod')
" 2>/dev/null
fi
# Go
if [ -f "go.sum" ]; then
echo "--- Go 依赖项 ---"
python3 -c "
import re
seen = set()
with open('go.sum') as f:
for line in f:
parts = line.strip().split()
if len(parts) >= 2:
name = parts[0]
version = parts[1].split('/')[0]
key = f'{name}@{version}'
if key not in seen:
seen.add(key)
print(f'{name}|{version}|UNKNOWN|prod')
" 2>/dev/null | head -50
fi
# Rust
if [ -f "Cargo.lock" ]; then
echo "--- Rust 依赖项 ---"
python3 -c "
import re
with open('Cargo.lock') as f:
content = f.read()
for match in re.finditer(r'name = "([^"]+)"nversion = "([^"]+)"', content):
print(f'{match.group(1)}|{match.group(2)}|UNKNOWN|prod')
" 2>/dev/null | head -50
fi
echo ""
echo "=== 许可证分析 ==="
# 对于 npm:许可证信息位于 package-lock.json 和 package.json 中
if [ -f "package-lock.json" ]; then
python3 -c "
import json
from collections import Counter
lock = json.load(open('package-lock.json'))
licenses = Counter()
unknown = []
for name, info in lock.get('packages', {}).items():
if not name: continue
lic = info.get('license', 'UNKNOWN')
if isinstance(lic, dict):
lic = lic.get('type', 'UNKNOWN')
licenses[lic] += 1
if lic == 'UNKNOWN':
unknown.append(name.replace('node_modules/', ''))
print('许可证分布情况:')
for lic, count in licenses.most_common():
print(f' {lic}: {count}')
if unknown:
print(f'n未知许可证(共 {len(unknown)} 个):')
for pkg in unknown[:10]:
print(f' {pkg}')
# 标记 Copyleft 类许可证
copyleft = ['GPL-2.0', 'GPL-3.0', 'AGPL-3.0', 'LGPL-2.1', 'LGPL-3.0', 'MPL-2.0', 'EUPL-1.2', 'SSPL-1.0']
risky = {l: c for l, c in licenses.items() if any(l.startswith(cp) for cp in copyleft)}
if risky:
print('n⚠️ 检测到 Copyleft 类许可证(可能限制分发):')
for lic, count in risky.items():
print(f' {lic}: {count}')
" 2>/dev/null
fi
echo ""
echo "=== 漏洞扫描 ==="
# npm audit
if [ -f "package-lock.json" ]; then
npm audit --json 2>/dev/null | python3 -c "
import json, sys
try:
d = json.load(sys.stdin)
vulns = d.get('metadata', {}).get('vulnerabilities', {})
total = sum(vulns.values())
print(f'npm 漏洞数量:{total}')
for severity in ['critical', 'high', 'moderate', 'low']:
count = vulns.get(severity, 0)
if count > 0:
icon = '❌' if severity in ['critical', 'high'] else '⚠️'
print(f' {icon} {severity}: {count}')
if total == 0:
print(' ✅ 未发现已知漏洞')
except:
print(' 无法解析 npm audit 输出')
" 2>/dev/null
fi
# pip-audit
if [ -f "requirements.txt" ] && command -v pip-audit &>/dev/null; then
pip-audit -r requirements.txt 2>/dev/null | head -20
fi
# Go 漏洞检查
if [ -f "go.sum" ] && command -v govulncheck &>/dev/null; then
govulncheck ./... 2>/dev/null | head -20
fi
cyclonedx — 生成 CycloneDX 格式 SBOM输出 CycloneDX 1.5 JSON 格式:
{
"bomFormat": "CycloneDX",
"specVersion": "1.5",
"serialNumber": "urn:uuid:",
"version": 1,
"metadata": {
"timestamp": "",
"tools": [{"name": "sbom-generator", "version": "1.0.0"}],
"component": {
"type": "application",
"name": "",
"version": ""
}
},
"components": [
{
"type": "library",
"name": "",
"version": "",
"purl": "pkg:npm/@",
"licenses": [{"license": {"id": ""}}],
"scope": "required"
}
]
}
spdx — 生成 SPDX 格式 SBOM输出 SPDX 2.3 JSON 格式。
licenses — 许可证合规报告仅聚焦于许可证分析:
## 许可证合规报告 ### 概要 - 总依赖数:247 - 宽松型许可证(MIT、Apache-2.0、BSD):231(93.5%) - Copyleft 类许可证(GPL、LGPL、MPL):8(3.2%) - 未知许可证:8(3.2%) ### 待处理事项 1. ❌ 3 个包采用 GPL-3.0 —— 可能需公开源代码 2. ⚠️ 8 个包许可证未知 —— 需人工核查 3. ✅ 231 个包采用宽松型许可证 —— 无分发限制
diff — 版本间 SBOM 差异比对对比两个 SBOM,识别变更内容:
新增依赖项: + @tanstack/react-query 5.0.0 (MIT) + zod 3.22.0 (MIT) 移除依赖项: - react-query 3.39.0 (MIT) - yup 1.2.0 (MIT) 版本变更: ~ react 18.2.0 → 18.3.0 ~ typescript 5.2.0 → 5.3.0 许可证变更: ~ some-package: MIT → Apache-2.0
policy — 基于许可证策略校验在 .sbom-policy.json 中定义允许/禁止的许可证:
{
"allowed": ["MIT", "Apache-2.0", "BSD-2-Clause", "BSD-3-Clause", "ISC", "0BSD", "Unlicense", "CC0-1.0"],
"denied": ["GPL-3.0", "AGPL-3.0", "SSPL-1.0"],
"review_required": ["GPL-2.0", "LGPL-2.1", "LGPL-3.0", "MPL-2.0", "EUPL-1.2"],
"allow_unknown": false
}
退出码说明:
allow_unknown 为 false--format cyclonedx 或 --format spdx 指定)name,version,license,scope,purl本能力支持以下合规要求:
相关专题
热门下载
相关下载
精品课程
共6课时 | 54.7万人学习
共89课时 | 134.1万人学习
共49课时 | 82.6万人学习
最新文章