许可证判断练习¶
主要作者
本节用途
这是第 3 次课「许可证与合规」的当次成果。练习以真实项目为素材,完成本节后你应当能够独立判断一个项目的许可证、判断自己的使用方式是否触发义务,并说明理由。
学习目标¶
完成本节后,你应当能够:
- 从仓库中定位许可证信息,并写出正确的 SPDX 标识符;
- 针对具体使用方式,列出需要履行的义务;
- 判断两个许可证能否组合,并给出理由;
- 用可追溯的方式(链接、
LICENSE原文、SPDX 标识符)记录你的判断依据。
一、先学会查证¶
在判断之前,先完成四个查证动作:
- 打开仓库根目录的
LICENSE(也可能是LICENSE.txt、COPYING、LICENSE.md),确认许可证名称与版本; - 查看包元数据中的许可证字段:
package.json的license、pyproject.toml/Cargo.toml的license、pom.xml的<licenses>; - 查看源码文件头是否使用 SPDX 标识符,例如
SPDX-License-Identifier: Apache-2.0; - 用 SPDX License List 核对标识符的标准写法。
仓库里的许可证可能不止一个
大型项目常见"混合许可":主目录一个许可证,某些子目录另有许可证(例如固件、文档、图标)。查看 LICENSES/ 目录、NOTICE、README 中的许可说明,以及文件级 SPDX 标识符。
二、练习 A:识别许可证并写出 SPDX 标识符¶
阅读下表项目的许可证,写出标准 SPDX 标识符。若项目存在许可证变更历史,请注明"当前"。
| # | 项目 | 你在 LICENSE 中会看到的名称 |
你的答案(SPDX) |
|---|---|---|---|
| 1 | Linux 内核 | GNU General Public License v2.0 | |
| 2 | Kubernetes | Apache License 2.0 | |
| 3 | React | MIT License | |
| 4 | Nginx | BSD 2-Clause "Simplified" License | |
| 5 | Go | BSD 3-Clause "New" or "Revised" License | |
| 6 | Mozilla Firefox | Mozilla Public License 2.0 | |
| 7 | glibc | GNU Lesser General Public License v2.1 or later | |
| 8 | Nextcloud | GNU Affero General Public License v3.0(or later) | |
| 9 | OpenTofu | Mozilla Public License 2.0 | |
| 10 | Valkey | BSD 3-Clause "New" or "Revised" License |
参考答案
GPL-2.0-only(注意:内核不是or-later)Apache-2.0MITBSD-2-ClauseBSD-3-ClauseMPL-2.0LGPL-2.1-or-laterAGPL-3.0-or-laterMPL-2.0BSD-3-Clause
易错点:第 1 题写成 GPL-2.0 或 GPLv2 不得分——SPDX 要求区分 only 与 or-later,这个区别直接决定兼容性判断。
三、练习 B:判断义务¶
对每个场景回答三个问题:(1) 我的产品可以闭源吗?(2) 我必须开源我的修改吗?(3) 我必须提供源码吗? 并写出一句理由。
| # | 场景 |
|---|---|
| 1 | 在闭源商业 App 中使用 MIT 许可的库 |
| 2 | 把 BSD-2-Clause 的组件嵌入自研闭源网关设备 |
| 3 | 修改 LGPL-2.1-or-later 的 glibc,并以动态链接方式用在对外分发的闭源产品中 |
| 4 | 基于 Apache-2.0 的 Kubernetes 制作闭源发行版并对外销售 |
| 5 | 修改 GPL-2.0-only 的 Linux 内核驱动,随硬件出货 |
| 6 | 原样运行 AGPL-3.0-or-later 的 Nextcloud,供员工在内网使用(未修改源代码) |
| 7 | 修改 AGPL-3.0-or-later 的 Nextcloud,部署为对外提供服务的 SaaS |
| 8 | 把 BUSL-1.1 的 Terraform 打包成托管服务对外售卖 |
| 9 | 修改 MPL-2.0 的 Firefox 中某一个源文件后分发整个浏览器 |
| 10 | 使用 ODbL-1.0 的 OpenStreetMap 数据生成衍生数据库并公开提供 |
参考答案与理由
- 可以闭源;不必开源修改;不必提供源码。 只需在产品中保留版权声明与 MIT 许可证文本。
- 可以闭源;不必开源修改;不必提供源码。 保留声明与免责声明即可。
- 可以闭源(你的程序);但你修改后的 glibc 需要以 LGPL 提供源码,并且必须让用户能够替换该库版本。 LGPL 是库级 copyleft,这些义务由向他人分发触发——本题题设即对外分发;若只在组织内部运行、不对外分发,则修改与运行本身都不触发源码提供义务。动态链接通常已满足「可替换」要求;静态链接需额外提供目标文件以便重新链接。
- 可以闭源;不必开源你的修改,也不必让修改部分继续采用 Apache-2.0。 Apache-2.0 第 4 节允许你以不同条款发布修改或衍生作品;你只需继续满足:保留版权与许可证声明、附上许可证文本、保留
NOTICE文件的内容、并在修改过的文件中标注修改。Apache-2.0 没有传染性——把它当成 copyleft 是常见误解。 - 不可以只在"整体"层面理解:内核是 GPL-2.0-only,分发即触发源码义务,必须提供修改后的内核源码(含你的驱动修改),以及构建与安装所需的脚本。你自己的用户态 App 若通过系统调用使用内核,通常不被视为衍生作品。
- 未修改时不触发第 13 条的源码提供义务。 AGPLv3 第 13 条的表述是"if you modify the Program"——它针对的是修改后的版本在用户通过网络与之交互时生效。因此原样部署并不自动产生源码义务(但仍须遵守许可证的其它条款、保留声明)。关键在"是否修改",不在"是否对外"。
- 必须向使用者提供对应源码。 第 13 条的触发条件是"修改 + 用户通过网络与之交互",没有内外部之分:修改后的版本必须向所有通过网络使用它的用户(包括公司内网的员工)显著提供获取对应源码的机会,且不以分发二进制文件为前提。"只在内网用""没有对外发布"都不是豁免理由。
- 不被允许。 BUSL-1.1 是 source-available 许可证,不是开源许可证;它限制把软件作为竞争性服务提供。需要与版权方另行取得商业授权。
- 需要提供所有 MPL 覆盖文件的源码,但不包括你自己的独立文件。 MPL-2.0 §3.2 规定:分发可执行版本时,必须提供全部 Covered Software(即所有以 MPL 授权的文件,无论你是否修改过)的 Source Code Form;你不能只提供自己改过的那一个文件。同时,MPL 的 copyleft 不扩散到你新增的、不属于 Covered Software 的文件——它们可以作为 Larger Work 的一部分保持闭源。这才是"文件级 copyleft"的准确含义。
-
公开使用衍生数据库时需要履行的不是一条义务,而是三条。 ODbL-1.0 里分别规定:
-
§4.4(Share Alike):你公开使用(Publicly Use)衍生数据库,该衍生数据库本身只能按 ODbL-1.0、其后续版本或兼容许可证授权;
- §4.6(Access to Derivative Databases):只要你公开使用衍生数据库,或公开使用由它产生的 Produced Work,就必须向接收者提供机器可读形式的:① 完整的衍生数据库,或 ② 包含你对原数据库所作全部改动的文件(例如算法或差分文件)。这条不要求你"以数据库形式分发"——公开一张由该衍生数据库生成的地图或报告同样会触发;经互联网提供时还必须免费;
- §4.3(Notice for using output):公开使用 Produced Work 时,必须附带足以让接触者知道"内容来自该数据库、且依本许可证提供"的声明。
需要区分的是:只在内部使用、既不公开使用也不分发时,不触发上述开放义务。
四、练习 C:兼容性判断¶
判断下列组合是否可以在同一个项目中同时使用。若不兼容,说明原因并给出两种可行的处理方式。
| # | 组合 |
|---|---|
| 1 | MIT 库 + GPL-3.0-only 主程序 |
| 2 | Apache-2.0 组件 + GPL-2.0-only 内核模块 |
| 3 | GPL-2.0-only 代码 + GPL-3.0-or-later 主程序 |
| 4 | MPL-2.0 库 + GPL-2.0-or-later 主程序 |
| 5 | SSPL-1.0 组件 + MIT 主程序(对外宣称项目"开源") |
参考答案与理由
- 兼容。 宽松许可证不附加冲突条件,组合后整体按
GPL-3.0-only履行义务,并保留 MIT 声明。 - 不兼容。
Apache-2.0的专利与免责条款附加了 GPLv2 不允许的额外限制;GPL-2.0-only又无法按 v3 使用。处理方式:① 由相关版权方专门授予兼容性例外(例如针对该代码的双许可声明)——注意内核COPYING中关于「正常使用系统调用」的说明只用于区分独立的用户态程序,并不构成让Apache-2.0代码进入GPL-2.0-only内核模块的通用例外;② 用独立进程/RPC 隔离,使两者不构成同一衍生作品;③ 换成GPL-2.0-only兼容的组件。 - 不兼容。
GPL-2.0-only明确不允许按后续版本使用,因此无法与 v3 代码链接。处理方式:① 取得把该组件按or-later授权的许可;② 替换为GPL-2.0-or-later版本或MIT/Apache-2.0组件。 - 有条件兼容。 MPL-2.0 原文 §1.12 把次级许可证定义为 GPL 2.0、LGPL 2.1、AGPL 3.0 以及这些许可证的后续版本;§3.3 允许在与次级许可证作品组合的 Larger Work 中,额外按该次级许可证分发 MPL 覆盖的代码。前提是 Covered Software 不属于 §1.5 定义的
Incompatible With Secondary Licenses:既没有初始贡献者附上的 Exhibit B 不兼容声明,也不是原先按 MPL 1.1 或更早版本提供、却未同时按次级许可证提供的代码。须逐个文件核查声明及原始授权历史,不能仅凭文件头没有 Exhibit B 声明就判定兼容。注意only后缀限制的是被许可人自行升级版本,并不把该版本排除出次级许可证列表。 - 不可以称为开源。 SSPL 未通过 OSD,不是开源许可证。处理方式:① 替换为
AGPL-3.0-or-later等真正的开源组件;② 明确项目定位为 source-available 并如实描述,不得声称开源。
五、练习 D:综合场景(固件产品)¶
某公司要发布一款智能音箱,技术栈如下:
- 内核:Linux(
GPL-2.0-only),并修改了两个驱动; - 用户态工具:一个
GPL-3.0-or-later的媒体解码工具,修改后静态编译进固件; - 自研 App:闭源,内部使用一个
MIT库和一个Apache-2.0库(含NOTICE文件); - 设备:启用安全启动,禁止用户刷入修改后的固件与内核。
请回答:
- 哪些部分必须提供源码?向谁提供?
- 自研 App 是否可以闭源?
- "禁止用户刷机"是否违反许可证?如果内核改用
GPL-3.0-only,结论会怎样变化? - 公司应当准备哪些合规材料?
参考答案与评分要点
- 必须提供:修改后的内核源码(含驱动修改)、修改后的
GPL-3.0-or-later解码工具源码,以及构建、安装所需的脚本与信息。提供对象是获得该二进制固件的任何用户(购买设备即获得)。MIT与Apache-2.0库不需要提供源码,但需随固件附带其许可证文本与NOTICE。 - 可以闭源。 自研 App 若未链接 GPL 代码(静态编译解码工具时需要确认是否与 App 构成同一作品,若构成则整个作品受 GPL 约束——这是本题的陷阱)。
- 在 GPLv2 下,"禁止刷机"本身不直接违反许可证,因为 v2 没有反 Tivoization 条款——这正是 Linux 内核停留在 GPLv2 的现实原因之一。若内核改用
GPL-3.0-only,第 6 条要求提供"安装信息"(Installation Information),使修改后的软件能够被安装并运行;此时继续用安全启动阻止用户刷机将违反 GPLv3。 - 至少准备:许可证清单与 SPDX 标识符、SBOM、修改文件的差异记录、源码获取方式(随附或可长期访问的下载地址)、第三方声明与
NOTICE汇总、合规审查记录。
评分要点:能否区分"分发触发"与"网络交互触发";能否识别静态编译带来的衍生作品风险;能否说明 GPLv2 与 GPLv3 在反 Tivoization 上的差异。
六、练习 E:找错¶
下面是一份同学提交的合规结论,请指出其中的所有错误并改正:
我们的产品使用了一个 MIT 许可的库和一个 GPL-3.0-or-later 的工具。因为 MIT 是"无传染"的,GPL 是"传染"的,所以整个产品必须开源。另外我们没有修改 GPL 工具,所以不需要提供源码。许可证写在 README 里就可以了,不必单独放 LICENSE 文件。
参考答案
错误 1:"整个产品必须开源"——错误。需要判断 GPL 工具与产品是否构成同一衍生作品。若只是独立进程调用,产品可闭源;若静态链接或复制代码,则整个作品受 GPL 约束。
错误 2:"没有修改就不需要提供源码"——错误。GPL 的义务源于分发,而不是修改。分发二进制时必须提供对应源码(即使未修改)。
错误 3:把 Apache-2.0 之外的许可证简化为"传染/无传染"二元——错误,忽略了 Apache-2.0(宽松但含专利条款)、MPL-2.0(文件级)等中间类型。
错误 4:"许可证写在 README 里就可以"——错误。应在仓库根目录放置完整的 LICENSE 文件,并在包元数据与源码文件头使用 SPDX 标识符;README 中的说明不能替代许可证文本。
七、评分标准¶
| 维度 | 分值 | 达标要求 |
|---|---|---|
| 许可证识别 | 20 | SPDX 标识符完全正确,能区分 only 与 or-later |
| 义务判断 | 30 | 四类行为(使用/修改/分发/网络服务)的判断准确,理由指向具体条款 |
| 兼容性判断 | 25 | 结论正确且能说明冲突来源,能给出可执行的替代方案 |
| 综合场景 | 15 | 能区分内核与用户态的边界,能说明 GPLv2/v3 的差异 |
| 证据与规范 | 10 | 判断均附 LICENSE 原文或 SPDX 链接,术语使用规范 |
完成标志
你能够对一个你从未见过的真实仓库,在 15 分钟内给出:SPDX 标识符、四类行为的义务判断、是否存在兼容性风险,以及一句可写入贡献提案的结论。