应使用 composer show --licenses --recursive --format=json 导出全部依赖许可证,composer 2.2+ 支持该命令;license 为空或 unknown 时需手动核查源码仓库 license 文件;json 输出可用 jq 或 grep 过滤,如 jq 'map(select(.license | contains("gpl") or contains("gpl")))'。

composer show --licenses 只显示顶层包,怎么导出全部依赖的许可证?
它默认不递归,composer show --licenses 只查 composer.json 里直接写的包,子依赖的许可证全被忽略。合规审计时这完全不够用。
- 必须加
--recursive参数才会展开整个依赖树 - 加上
--format=json更方便后续解析(比如转 CSV 或过滤 MIT/AGPL) - 注意:Composer 2.2+ 才支持
--recursive,旧版本会报错Unrecognized option: --recursive
推荐命令:composer show --licenses --recursive --format=json > licenses.json
许可证字段为空或显示 unknown 怎么办?
很多包的 composer.json 没填 license 字段,或者填了但值不规范(比如 "license": "BSD-3-Clause" 是对的,"license": "BSD" 就常被识别为 unknown)。
- 空 license 不代表无许可,只是元数据缺失;得手动查对应包的
LICENSE文件或 GitHub 主页 -
composer show不读取实际 LICENSE 文件内容,只读composer.json的license字段 - 遇到
unknown,优先检查该包的源码仓库根目录,别信 Packagist 页面上“自动提取”的 license 标签
想按许可证类型筛选(比如只导出 GPL 相关包)
JSON 输出结构是扁平数组,每项含 name、version、license 字段,适合用 jq 过滤。
- 查所有含 GPL 的:
composer show --licenses --recursive --format=json | jq 'map(select(.license | contains("GPL") or contains("gpl")))' - 注意大小写:有些包写
"GPL-2.0-only",有些写"gpl-3.0",建议用ascii_downcase统一处理 - 如果没装
jq,临时用grep -i gpl也行,但会漏掉跨行或嵌套结构里的匹配
为什么 vendor/composer/installed.json 里 license 字段和 show 命令结果不一致?
因为 installed.json 存的是安装时抓取的原始元数据,而 composer show 会做归一化处理(比如把 MIT、mit、"The MIT License" 都映射成 MIT)。
- 合规审计应以
composer show --licenses --recursive为准,它调用了 Composer 内部的 license 解析器 - 直接读
installed.json容易误判——例如"license": ["proprietary"]在 installed.json 里是数组,show 命令会转成字符串proprietary - 另外,
installed.json不包含 require-dev 的包,而--recursive默认包含(除非加--no-dev)
真正麻烦的是那些没声明 license 却在运行时动态加载代码的包,比如某些 fork 后删了 LICENSE 文件的私有组件——这种只能靠人工核对,工具扫不出来。










