不能用 composer show 生成生产级 sbom,因其仅输出顶层声明包,缺失许可证、哈希、purl、源仓库 url 等关键字段,不包含传递依赖与运行时结构,且非 cyclonedx/spdx 标准格式;正确做法是用 syft php:./vendor 扫描实际安装目录,生成合规 sbom 并绑定制品上传。

为什么不能用 composer show 生成生产级 SBOM
它只输出 composer.json 里声明的顶层包,漏掉 require-dev 工具链(如 phpunit)、所有传递依赖(比如 monolog → psr/log),也不带许可证、SHA256 哈希、PURL 或来源仓库 URL。Defender for Cloud、DependencyTrack 这类工具根本无法解析或信任这种输出。
更关键的是:composer show 不反映实际加载结构——vendor/autoload.php 的类加载顺序、符号链接路径、替换包(replace)等运行时真实状态全无体现。
- 输出无标准 schema,不是 CycloneDX/SPDX 格式,不能被合规扫描器消费
- 没绑定构建上下文(commit SHA、CI job ID),无法追溯到具体发布版本
- 本地执行一次就过期,没法集成进 CI 流水线自动触发
syft 扫描 vendor/ 目录才是正确做法
必须在 composer install --no-dev 完成后立即执行,确保 vendor/ 是生产环境真实结构。Syft 能从文件系统递归提取每个已安装包的完整元数据:名称、版本、许可证、PURL、SHA256、来源仓库,且原生支持 PHP Composer 解析器。
命令要加 php: 前缀,避免误识别为 Ruby 项目:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
syft php:./ --output cyclonedx-json=sbom.cdx.json --file-type json
- 不要扫描整个项目根目录,否则
composer.lock可能被当成 Gemfile - 若用 Azure Pipelines,需在
UsePhp@1后立刻运行,防止缓存导致vendor/缺失 - 输出格式优先选
cyclonedx-json,兼容 Defender for Cloud 和 Grype
SBOM 必须和制品绑定上传,不能只存 artifact
SBOM 文件脱离对应制品就失去意义。GitHub Release 是最轻量、最可追溯的绑定方式——它提供公开、稳定、带签名的下载 URL,外部工具(如 DependencyTrack)可通过 webhook 自动拉取。
在 GitHub Actions 中,应在打包步骤之后插入 syft,再用 actions/upload-release-asset@v1 上传:
sbom-cyclonedx-${{ github.sha }}.json
- 文件名含 commit SHA,便于关联代码快照
- 绝对不要用 pipeline artifact 存 SBOM:它不对外暴露 URL,无法被安全平台集成
- 如果发布的是 Docker 镜像,直接
syft your-image-name扫描镜像层,比先docker save再解压更准
CI 中容易忽略的三个硬性条件
SBOM 生效的前提不是“跑通命令”,而是满足三个刚性约束:
-
composer install必须带--no-dev,否则开发依赖污染生产清单 -
vendor/目录必须由当前 CI job 实际生成,不能靠缓存或挂载复用旧内容 - SBOM 输出路径必须在制品打包逻辑之后,且上传动作不可跳过或条件化
少一个,生成的 SBOM 就只是个 JSON 文件,不是能被安全团队真正用起来的供应链证据。










