composer audit 不是矩阵生成工具,它只返回 advisory 列表且跳过 dev 分支、私有包和网络异常时失败;可靠依赖快照须用 composer show --format=json 结合 lock 文件哈希与 php 版本标记三者组合。

不能直接“生成安全矩阵”,composer audit 只能查已知漏洞,不输出完整依赖快照;真要构建可复现、可比对的版本矩阵,得靠 composer show --format=json + 锁文件哈希 + PHP 版本标记三者组合。
为什么 composer audit 不是矩阵生成工具
它只返回 advisory 列表,不输出包名、版本、来源或安装状态。哪怕项目有 127 个依赖,只要没匹配到 CVE 数据库条目,就只打印 No security vulnerabilities found。更关键的是:
-
composer audit跳过所有dev-、dev-main和带-dev后缀的版本(数据库不收录不稳定分支) - 私有包、
path类型仓库、fork 包默认不参与扫描 - 网络不可用时直接失败,连空结果都不返回
composer show --format=json 才是可靠的数据源
它读取 composer.lock,输出当前 vendor 中真实安装的每个包的精确信息,不含任何外部依赖或网络调用。实操要点:
- 必须确保
composer.lock已提交且未被.gitignore过滤,否则composer show会报错或返回空 - 加
--installed-only参数可排除因--no-dev被跳过的 dev 包,避免混淆生产/测试环境边界 - 导出命令示例:
composer show --format=json --installed-only > deps-${{ matrix.php-version }}-$(sha256sum composer.lock | cut -c1-8).json - JSON 字段含
name、version、source、dist,但不含安全状态——这正是矩阵需要的“原始事实”
GitHub Actions 中如何拼出完整矩阵
单靠一个 JSON 文件不够,矩阵本质是多维快照对比。关键不是“生成”,而是“采集+标记+归档”。需在 workflow 中固化三个维度:
-
PHP 版本:用
${{ matrix.php-version }}显式标记,不同版本可能触发不同依赖解析路径 -
lock 文件指纹:用
${{ hashFiles('composer.lock') }},而非文件名或时间戳,确保语义一致 -
执行环境标识:加
runner.os和composer --version哈希,避免缓存污染导致的 vendor 错配
归档路径建议:artifacts/deps/php-${{ matrix.php-version }}-${{ hashFiles('composer.lock') }}.json。别把 JSON 当报告直接展示——它是后续做 diff、比对、审计的原子输入。
容易被忽略的陷阱:vendor 目录 ≠ 矩阵数据源
有人试图遍历 vendor/ 目录抓取 composer.json 来拼版本,这是危险的。因为:
- 某些包(如
symfony/*)会把composer.json构建进 phar 或删掉,目录里根本不存在 -
vendor/可能混入本地修改、未提交的 patch,而composer.lock记录的是 Git tag 或 dist hash - CI 中若用了
--no-dev,vendor/里缺 dev 包,但composer show默认仍列它们——除非加--installed-only
矩阵的可信度,取决于你是否严格以 composer.lock 为唯一真相源,其他都是衍生视图。











