PHPLIB-1866: Add automated SBOM generation using cyclonedx-php-composer#1921
Conversation
Adds a two-stage SBOM pipeline following the pattern established in mongo-csharp-driver, mongo-go-driver, and mongo-python-driver: - GitHub Actions (.github/workflows/sbom.yml): generates sbom.json from production Composer dependencies via cyclonedx-php-composer v5, validates with cyclonedx-cli, and opens a PR when composer.json changes on v2.x. Version tracking increments .version only when content changes. - Evergreen (.evergreen/config/sbom.yml + upload-sbom.sh): uploads the committed sbom.json to the internal SSDLC tracking system via silkbomb augment, triggered when sbom.json changes. Soft-fails if the augmented SBOM changes significantly. sbom.json updated with correct production dependencies (psr/log, polyfill-php85) and stable serial number.
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Introduces automated generation, validation, and upload plumbing for a CycloneDX SBOM, and updates the committed sbom.json to the newly generated output.
Changes:
- Regenerates
sbom.jsonwith updated metadata, components, and dependency graph. - Adds a GitHub Actions workflow to regenerate/validate SBOM and open an auto-update PR when it changes.
- Adds Evergreen task/functionality to augment and upload SBOM via Silkbomb.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
sbom.json |
Updates the committed CycloneDX SBOM content and version metadata. |
.github/workflows/sbom.yml |
Automates SBOM generation/validation and opens a PR when sbom.json changes. |
.evergreen/generate-sbom.sh |
Generates sbom.json and manages a stable serial number + incremental versioning. |
.evergreen/upload-sbom.sh |
Runs Silkbomb augmentation and reports significant augmented SBOM changes to Evergreen. |
.evergreen/config/sbom.yml |
Adds an Evergreen buildvariant/task to run SBOM upload. |
.evergreen/config/functions.yml |
Adds an upload-sbom function integrating AWS role assumption and upload script execution. |
.evergreen/config.yml |
Includes the new Evergreen SBOM config file. |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
- Use temp files for SBOM content comparison in generate-sbom.sh instead of shell variable capture - Add jq -S (sort keys) to workflow diff steps to avoid false-positive diffs from key reordering
paulinevos
left a comment
There was a problem hiding this comment.
Thanks for this. Main things:
- I wonder if some of the hardcoded stuff could be replaced.
- Do we actually need to commit the sbom.json and create a PR if it's only used to upload internally? Feels like maybe we could let CI generate it on every major/minor release and just upload it then? As long as we keep locking and validating the version hashes
| --output-format=JSON \ | ||
| --output-file=sbom.cdx.json \ | ||
| --omit dev \ | ||
| --no-validate |
There was a problem hiding this comment.
It is redundant, as we do a more thorough validation downstream that provides better output for resolution of the issue. Added in a clarifying comment.
| if ! diff -sty --left-column -W 200 "$old_json" "$new_json" > "$diff_txt"; then | ||
| declare status | ||
| status='{"status":"failed", "type":"test", "should_continue":true, "desc":"detected significant changes in Augmented SBOM"}' | ||
| curl -sS -d "${status}" -H "Content-Type: application/json" -X POST http://localhost:2285/task_status || true |
There was a problem hiding this comment.
Do we want the host/port hardcoded here?
There was a problem hiding this comment.
Added clarifying comment: Evergreen's agent opens an HTTP server on localhost:2285 during task execution. Posting to /task_status marks the task as failed while allowing it to continue so that subsequent upload steps (e.g., artifact archiving) can still run.
I have changed it to only upload the SBOM when the dependency definitions change. Nothing gets checked in to the repo. Expanded use of Dependabot will keep you current and should closely mirror what is identified by internal scanners. If anything slips through, a Jira ticket will be opened for tracking purposes. |
- Remove GitHub Actions workflow: generation and upload now handled entirely in Evergreen, triggered on composer.json changes to v2.x - Replace silkbomb augment with silkbomb upload; remove augmented SBOM comparison and soft-fail logic from upload-sbom.sh - Add generate-sbom Evergreen function; upload-sbom task now generates then uploads in one step - Remove committed sbom.json; SBOM is generated fresh on each run - Remove version tracking from generate-sbom.sh - Name role ARNs with YAML anchors in functions.yml - Add Dependabot composer config (production deps only, daily schedule) - Add --no-validate comment in generate-sbom.sh
composer require modifies composer.json; save and restore it in generate-sbom.sh so the plugin is not added to the project.
| # None required — all inputs are derived from the repository. | ||
| set -eo pipefail | ||
|
|
||
| SERIAL_NUMBER="urn:uuid:dc42a43b-4ace-4c42-9a6e-0b9e28fdd100" |
| paths: | ||
| - composer.json |
There was a problem hiding this comment.
Choice was made not to check in the composer.lock in #158 .
GromNaN
left a comment
There was a problem hiding this comment.
Thanks for automating the SBOM generation and removing the stale static sbom.json!
One concern: the publish-ssdlc-assets job in release.yml passes sbom.json as input to drivers-github-tools/sbom@v3 (silkbomb update), so deleting it will break the release workflow.
Since SBOM tracking is only required at release time anyway, would it make sense to consolidate everything into release.yml rather than adding a separate Evergreen pipeline? Concretely, adding a "Generate SBOM" step in publish-ssdlc-assets (running the same cyclonedx-php-composer logic) just before the full-report@v3 call would:
- Generate a fresh SBOM from the release tag
- Feed it directly into the existing
silkbomb update/augment/ upload chain - Eliminate the need for the Evergreen
sbombuild variant - Remove
sbom.jsonfrom the repo without breaking anything
The main trade-off is losing continuous tracking on every composer.json commit — but if that's not a hard requirement from the security team, a single release-time upload should satisfy the SSDLC policy. Is continuous tracking a requirement here?
Summary
This PR adds automated CycloneDX 1.5 SBOM generation and upload for the PHP library. SBOM generation and upload are handled entirely within Evergreen — no GitHub Actions involvement and no SBOM file committed to the repository.
Architecture
Evergreen (
.evergreen/config/sbom.yml)Triggered on commits to
v2.xwhencomposer.jsonchanges. Theupload-sbomtask:.evergreen/generate-sbom.sh— installscyclonedx/cyclonedx-php-composer:6.2.0, runscomposer update --ignore-platform-reqs --no-scriptsto resolve a fresh dependency graph, generates a CycloneDX 1.5 JSON SBOM from production dependencies only (--omit dev), and injects a stable serial number..evergreen/upload-sbom.sh— authenticates to ECR, pullssilkbomb:2.0, and callssilkbomb uploadto submit the SBOM to the internal tracking system.Files changed
.evergreen/generate-sbom.sh— SBOM generation script.evergreen/upload-sbom.sh— silkbomb upload script.evergreen/config/functions.yml—generate-sbomandupload-sbomEvergreen functions; role ARNs named with YAML anchors.evergreen/config/sbom.yml—upload-sbomtask andsbombuild variant.evergreen/config.yml— include forsbom.yml.github/dependabot.yml— include composer package ecosystem forproductiondependencies for visibility ahead of internal scanningDependabot
Recommend continued use of Dependbot to keep dependencies current. Dependabot results closely mirror results from internal scanners for the Composer ecosystem.