composer show 输出不是合规 sbom,因其缺失许可证、哈希值、purl/cpe、源仓库 url 等关键字段,且为扁平快照,无法反映嵌套依赖与安装方式;而 syft 扫描 vendor/ 可递归提取完整元数据,生成符合 cyclonedx/spdx 标准的真正 sbom。

不能只用 composer show 导出依赖就当安全清单交差——它缺许可证、没哈希、不带嵌套路径,SCA 工具根本没法 ingestion。
为什么 composer show --format=json 不是合规 SBOM
它输出的是 vendor/ 下已安装包的扁平快照,字段只有 name、version、description 和 source.type,但安全审计真正需要的:license 字段全空、purl 和 cpe 不存在、sha256 哈希值为零、没有组件来源仓库 URL,更不区分 dist vs source 安装方式。Defender for Cloud 或 DependencyTrack 拿到这种 JSON,会直接跳过解析或报 schema mismatch 错误。
常见错误现象:
- 用
jq '.[] | "\(.name) \(.version) \(.license // "UNKNOWN")"'提取时,90% 的.license是 null,结果全是 UNKNOWN - 把
composer show --no-dev --format=json上传给 Snyk,提示 “No valid components found” - 在 CI 中跑完
composer install --no-dev后立刻导出,却漏掉某些传递依赖(如psr/log被monolog引入但未显式出现在show输出里)
生产环境必须用 syft 扫描 vendor/ 目录
syft 是唯一能从实际文件系统结构中提取完整元数据的工具:它递归读取 vendor/ 每个包的 composer.json、package.xml、README,甚至尝试从源码注释中推测许可证;自动计算每个目录的 sha256;生成标准 CycloneDX 或 SPDX 格式,字段对齐 CNCF SBOM 最佳实践。
实操要点:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 必须在
composer install --no-dev成功后执行,否则vendor/缺包导致扫描遗漏 - 命令要加
--scope local并显式指定解析器:syft php:./vendor --output sbom.cdx.json -o cyclonedx-json,否则可能误判为 Ruby/Git 项目 - 不要扫描整个项目根目录——
syft .会把composer.json当作 manifest,漏掉 vendor/ 里实际加载的类路径信息 - Azure Pipelines 中需在
UsePhp@1后立即运行,避免因 job 缓存导致vendor/为空
composer export --without-dev 是审计前最小可信快照
当你要把依赖清单喂给 Dependabot 或做基线比对,composer export --format=lock --without-dev > composer-prod.lock 比 composer show --no-dev 更可靠:它不是过滤显示,而是基于当前 composer.lock 重建一个不含 require-dev 字段、且已剔除所有 dev-only 包及其子依赖的新 lock 文件。
注意条件:
- 必须已执行过至少一次
composer install或composer update,否则报错Lock file does not contain required packages - 该命令不继承
platform-check配置,若项目强制 PHP 8.2,需额外确认composer-prod.lock中的platform字段是否保留 - 生成的
composer-prod.lock可被composer install --no-dev --ignore-platform-reqs正常消费,适合离线环境部署验证
GitHub Release 绑定 SBOM 才算闭环
SBOM 文件如果只是存在 CI 日志或临时 artifact 里,等于没生成。DependencyTrack 无法 webhook 拉取 artifact,Grype 也没法自动关联 commit SHA。
正确做法:
- 在打包步骤(如生成
app.phar或dist.zip)之后,插入syft步骤 - 把
sbom.cdx.json作为 asset 上传到 GitHub Release,文件名含 commit SHA:sbom-cyclonedx-$(git rev-parse --short HEAD).json - 避免用
actions/upload-artifact存 SBOM——它不暴露公开 URL,外部工具无法直连 - 若发布 Docker 镜像,改用
syft your-image:tag直接扫描镜像层,比先docker save再解压快且准确
真正难的从来不是“怎么生成”,而是每份 SBOM 是否绑定了构建上下文:它对应哪个 git commit、是否启用 platform-check、有没有 --no-dev、content-hash 是否与线上环境一致。丢掉这些,SBOM 就只是又一个没人敢信的 JSON 文件。










