Compares two CycloneDX or SPDX SBOMs to surface net-new, removed, and version-changed components between image or build versions; uses cyclonedx-cli diff for structured output and syft-based generation for the input SBOMs; gates CI on net-new component introduction; enables supply-chain alerting when unexpected dependencies appear across releases. Use when the team needs to detect dependency drift between container image builds, release candidates, or dependency-update branches.
75
94%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Medium
Suggest reviewing before use
Full GitHub Actions workflows extracted from sbom-diff. The SKILL.md spine
keeps the minimal jq gate; the complete CI-gate job, the allowlist pattern,
and the nightly drift-detection workflow live here.
- name: SBOM diff gate
run: |
ADDED=$(jq '.added | length' diff-result.json)
echo "Net-new components: $ADDED"
if [ "$ADDED" -gt "0" ]; then
echo "::error::Net-new components detected. Review diff-result.json."
jq '.added' diff-result.json
exit 1
fiTo allow a pre-approved set of additions (a known intentional dependency upgrade), maintain an allowlist and subtract matches before the count check:
UNAPPROVED=$(jq --rawfile allow allowlist.txt \
'[.added[] | select(.name as $n | $allow | test($n) | not)] | length' \
diff-result.json)Adjust the gate threshold and allowlist policy to the team's change-control requirements; the CI step above enforces zero-tolerance as the strictest form.
For production image monitoring, run a nightly diff against the last known-good SBOM rather than comparing two build artifacts:
jobs:
sbom-drift:
runs-on: ubuntu-latest
schedule:
- cron: "0 2 * * *"
steps:
- name: Generate current SBOM
run: syft myapp:production -o cyclonedx-json=sbom-current.json
- name: Download last known-good SBOM
run: |
aws s3 cp s3://sbom-store/sbom-last-good.json sbom-baseline.json
- name: Diff
run: |
cyclonedx diff sbom-baseline.json sbom-current.json \
--component-versions --output-format json \
> drift-result.json
- name: Alert on drift
run: |
ADDED=$(jq '.added | length' drift-result.json)
REMOVED=$(jq '.removed | length' drift-result.json)
if [ "$ADDED" -gt "0" ] || [ "$REMOVED" -gt "0" ]; then
echo "Supply-chain drift detected"
cat drift-result.json
# Pipe to Slack/PagerDuty/JIRA as needed
exit 1
fi
- name: Rotate known-good on clean diff
if: success()
run: aws s3 cp sbom-current.json s3://sbom-store/sbom-last-good.jsonThe "rotate known-good on clean diff" step ensures the baseline advances only when the image passes the gate, catching regressions introduced in a later build.