开源许可证合规
本页提供:license-checker/FOSSA 命令行扫描示例、MIT/Apache/GPL/LGPL 许可证兼容性矩阵表、自动生成 NOTICE 文件的命令、CI 中阻断 GPL 库的配置,以及 SPDX JSON 包片段实验室。
SKILL 内置组织级「允许 / 需法务评审 / 禁止」许可证表,并要求扫描结果与 lockfile 一致;对 UNKNOWN 或双重许可需人工确认。分发二进制或 SaaS 时对源码提供、版权声明与 NOTICE 聚合的要求不同,Agent 应区分交付形态并列出需随包附带的文件清单。
扫描工具命令与 CI 阻断配置
license-checker / FOSSA 命令行扫描
# license-checker(Node.js 项目)
npx license-checker --production \
--onlyAllow 'MIT;Apache-2.0;BSD-2-Clause;BSD-3-Clause;ISC;CC0-1.0' \
--excludePackages 'myapp@1.0.0' \
--json > license-report.json
# 列出所有许可证(含依赖树)
npx license-checker --production --csv > licenses.csv
# FOSSA CLI 扫描(需要 FOSSA_API_KEY)
fossa analyze --branch main
fossa test --timeout 600 # 非零退出表示策略不合规
# Python 项目 — pip-licenses
pip install pip-licenses
pip-licenses --format=json \
--with-urls \
--with-authors \
--output-file=licenses.json
# 自动生成 NOTICE 文件
npx license-checker --production \
--customFormat='{"name":"","version":"","licenses":"","copyright":""}' \
--out NOTICE \
--customPath notice-template.json
CI 中阻断 GPL 库(GitHub Actions)
# .github/workflows/license-check.yml
name: License Compliance
on: [pull_request]
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '20' }
- run: npm ci --production
- name: Check licenses (deny GPL)
run: |
npx license-checker --production \
--onlyAllow 'MIT;Apache-2.0;BSD-2-Clause;BSD-3-Clause;ISC;CC0-1.0;Unlicense' \
--excludePackages 'approved-exception@1.0.0' || \
(echo "::error::发现不允许的许可证,请检查 license-report.json" && exit 1)
- name: Upload report
uses: actions/upload-artifact@v4
with:
name: license-report
path: license-report.json
合规主流程(lockfile → 扫描 → SBOM)
[ lockfile / 构建图 与 组织允许表 对齐 ]
│
▼
┌─────────────┐ 解析 SPDX License Expression;标记 UNKNOWN / OR / AND
│ 依赖扫描 │──── 冲突:copyleft × 闭源分发、专利授予、附加义务
└─────────────┘
│
▼
┌─────────────┐ CycloneDX / SPDX JSON:每组件 licenseDeclared / concluded
│ SBOM 产出 │──── 版本漂移时 diff 许可证字段 → 触发合规复查工单
└─────────────┘
│
▼
┌─────────────┐ NOTICE / 源码义务 / UI 致谢;例外登记与到期日
│ 分发与文档 │──── 非法律意见 → 重大风险升级法务
└─────────────┘
流程要点:扫描器声明的 SPDX ID 与包元数据不一致时,以可追溯证据(官方 LICENSE 文件、SPDX 文档)为准,并在 SBOM 中保留 NOASSERTION 或注释说明直至闭环。
许可证兼容性矩阵
常见许可证在不同分发场景下的使用限制(非法律意见,重大决策转法务确认):
| 许可证 | 商业闭源使用 | 静态链接分发 | SaaS(不分发二进制) | 主要要求 |
|---|---|---|---|---|
MIT |
✅ | ✅ | ✅ | 保留版权声明与许可证文本 |
Apache-2.0 |
✅ | ✅ | ✅ | NOTICE 文件随包;专利授予(双向) |
LGPL-2.1 |
⚠️ | ⚠️ 需动态链接或提供目标文件 | ✅ | 允许闭源应用动态链接;修改 LGPL 库本身需开源 |
GPL-3.0 |
❌ 需法务评审 | ❌ 要求整个程序 GPL | ⚠️ AGPL-3.0 更严(网络服务也触发) | Copyleft 感染;分发须开放全部源码 |
NOASSERTION:元数据缺失且未人工确认前用于 SBOM 字段占位。- 扫描器输出的
UNKNOWN必须进入评审队列,不得静默映射为允许。
SBOM 中的许可证字段与复查
CycloneDX 的 licenses、SPDX JSON 的 licenseDeclared / licenseConcluded 应与 CI 扫描及 lockfile 同源;合并 PR 时对比上一版 SBOM 的许可证集合差异。
建议自动化
- 每次发布产物附带 SPDX 或 CycloneDX,与镜像 / 制品 digest 绑定。
- 许可证变更打标签或阻塞合流(按组织策略)。
- 将 SBOM 导入漏洞与许可证仪表板,统一 UNKNOWN 工单。
人工 / Agent 核对
- 双重许可下实际选用的条款与分发方式是否一致。
- 传递依赖升级引入的 copyleft 是否在允许表内。
- 例外批准记录、复审日期与责任人。
允许清单、分发形态与 NOTICE
静态链接、动态链接、容器分发与纯 SaaS 对「源码提供」「版权声明」的要求不同;SKILL 应要求 Agent 按交付形态列出需随包文件(LICENSE、NOTICE、第三方列表)。
组织级允许表应版本化并与流水线门禁一致;例外须带 ticket、批准人与复审日期。UI「关于 / 开放源代码许可」页应与 SBOM 或构建时生成的致谢文件同源生成,避免手抄漂移。
SPDX JSON 包片段实验室
填写组件坐标与 SPDX 许可证表达式,生成可合并进 SPDX 2.3 JSON SBOM 的单个 packages[] 元素示意(需按你方 SPDXID 命名空间与关系边补全)。
此为示意片段;完整 SBOM 还需 spdxVersion、dataLicense、SPDXID 文档根、relationships 等。CycloneDX 用户可将许可证信息映射到 components[].licenses。
---
name: license-compliance-cn
description: 扫描依赖许可证,核对兼容性矩阵,自动生成 NOTICE,在 CI 中阻断 GPL 库
---
# 步骤
1. 运行 license-checker --production --onlyAllow 'MIT;Apache-2.0;BSD-*;ISC'
2. 检查输出:UNKNOWN 和 GPL 类需人工评审,进入工单队列
3. 查对兼容性矩阵:静态链接 vs 动态链接 vs SaaS 三种分发形态的要求不同
4. 生成 NOTICE 文件:license-checker --customFormat + 模板输出
5. 生成 SBOM 中的 licenseDeclared 字段:与 lockfile 同源,不手工填写
6. CI 阻断:GitHub Actions 中 --onlyAllow 不通过则非零退出阻塞 PR 合并
7. FOSSA 集成(可选):fossa analyze + fossa test --timeout 600
8. 双重许可(OR):选择对业务最有利的条款并记录在工单中
9. Apache-2.0:确保 NOTICE 文件随包分发;注意专利授予条款
10. LGPL:确认是否动态链接;静态链接需法务确认
11. GPL 例外申请:附 ticket、批准人、到期复审日期
12. UI「开放源代码许可」页:从 SBOM 自动生成,不手工维护
# 禁止
- 禁止将 UNKNOWN 静默映射为允许
- 禁止将 GPL/AGPL 库与闭源代码静态链接未经法务评审
- 非法律意见:重大决策转交法务确认