composer licenses 命令仅显示项目自身 license 字段,不扫描依赖;真正全量检查依赖许可证的原生命令是 composer show --licenses,需已执行 install/update,输出含所有已安装包的 name、version、license 字段。

composer licenses 命令在 Composer 2.2+ 中存在,但它只显示你当前项目的 license 字段,不列任何依赖包的许可证。这不是 bug,是它的实际行为——很多人运行后只看到一行 myapp/myproject → MIT,就以为“全量扫描完成了”,结果法务审核时发现 90% 的第三方库许可证根本没查。
为什么 composer licenses 不是你想找的命令?
它不读 vendor/,不解析 composer.lock,也不递归检查依赖。官方文档未明确说明这点,导致大量误用。
- 输出恒为单行(或空),内容仅来自你项目根目录的
composer.json中的"license"字段 - 即使你已执行过
composer install,它也不会多输出一个依赖包 - 若你的项目
composer.json里没写license,它可能直接报错或静默退出
composer show --licenses 是真正能扫全量依赖的原生命令
这是目前 Composer 官方唯一稳定支持、且覆盖全部已安装包的许可证查看方式(2.1.12+ 起可用)。
- 必须先运行过
composer install或composer update,否则vendor/为空,命令会失败 - 加
--no-dev可排除require-dev中的包,适合生产环境审计 - 加
--format=json输出结构化数据,字段包括name、version、license,但注意:license可能是字符串、数组,也可能为null或 URL - 不支持
--recursive参数(旧教程里有,但 2.5+ 已移除),它本身就会遍历整个vendor/目录
CI 环境下怎么绕过 vendor/ 直接查许可证?
当 CI 流水线不想装完整 vendor/(比如只做合规卡点),应直接解析 composer.lock:
- 用
jq -r '.packages[] | "\(.name)\t\(.version)\t\(.license // ["unknown"] | join(" | "))"' composer.lock - 该方式不依赖
vendor/,但部分嵌套依赖可能未在packages数组中显式声明license字段,导致漏报 -
composer.lock中的license字段值同样未经标准化:可能是"MIT"、["BSD-3-Clause", "GPL-2.0"],甚至"https://example.com/LICENSE" - 若需更高覆盖率,可配合
.packages-dev[]和.packages[]两路提取
license 字段只是线索,不是法律依据
你看到 "license": "MIT",不代表这个包真受 MIT 许可约束;看到 "license": "unknown",也不代表它没许可——它可能只是作者忘了填,或者 LICENSE 文件在 GitHub 根目录下。
- 必须人工核对对应包源码仓库中的
LICENSE或LICENSE.md文件全文 - 用
grep -r -i "GNU GENERAL PUBLIC LICENSE.*v3" vendor/monolog/monolog/比看字段更可靠 - SPDX 标识符(如
GPL-3.0-only)才具备工具识别基础;GPL-3.0和GPL-3.0-or-later法律效力不同,不能混用 - 遇到
proprietary、unlicensed、空值,或模糊描述(如"The MIT License"),一律视为高风险,需人工确认
实际合规审查中,最常被跳过的一步是去源码仓库翻 LICENSE 文件——不是命令跑不出来,而是人懒得点开链接。











