syft-generation
Generates Software Bill of Materials (SBOMs) using Anchore Syft - supports container images / directories / archives across OCI / Docker / Singularity formats; output formats CycloneDX-JSON / SPDX-JSON / Syft-JSON / table / GitHub-JSON; pairs with `grype-scanning` for SBOM-driven vuln scanning. Use when the team needs SBOM artifacts for compliance (US EO 14028, EU CRA, FDA medical-device guidance) or as input to vuln scanners.
syft-generation
Overview
Syft generates SBOMs from "container images, filesystems, archives" with multi-container-standard support (OCI, Docker, Singularity). The generated SBOM is the input artifact for vuln scanning (grype-scanning) and compliance delivery (SPDX or CycloneDX format per consumer requirement).
Why generate SBOMs:
When to use
Step 1 - Install
Per sf-gh:
# curl install
curl -sSfL https://get.anchore.io/syft | sudo sh -s -- -b /usr/local/bin
# Homebrew
brew install syft
# Docker
docker run --rm -v "$PWD:/scan" anchore/syft scan dir:/scan -o cyclonedx-jsonOther paths (consult sf-gh): Scoop, Chocolatey, Nix.
Step 2 - Basic SBOM generation
Per sf-gh:
# Container image
syft alpine:latest
# Local directory
syft ./my-project
# Specific output format to stdout
syft <image> -o cyclonedx-json
# Multiple formats to files in one pass
syft <image> -o spdx-json=./spdx.json -o cyclonedx-json=./cdx.jsonThe default output is the table format (human-readable); use explicit -o for machine-readable formats in CI.
Step 3 - Output format catalog
Per sf-gh format support:
| Format | Use |
|---|---|
cyclonedx-json | CycloneDX 1.5+ JSON; broad ecosystem support |
cyclonedx-xml | CycloneDX XML (older toolchains) |
spdx-json | SPDX 2.3 JSON; preferred by US Federal procurement |
spdx-tag-value | SPDX tag-value format (legacy) |
syft-json | Syft-native JSON; richest metadata |
table | Human-readable terminal table (default) |
github-json | GitHub dependency-graph submission format |
For grype-scanning input, use syft-json (richest metadata) or cyclonedx-json (broader compat).
For compliance delivery, the consumer's requirement dictates - SPDX-JSON for US federal, CycloneDX-JSON for most EU contexts.
Step 4 - Source types
Per sf-gh supported sources:
| Source | Syntax |
|---|---|
| Local Docker daemon | syft alpine:latest |
| OCI / remote registry | syft registry:docker.io/alpine:latest |
| OCI archive (tar) | syft oci-archive:./image.tar |
| Docker archive (tar) | syft docker-archive:./image.tar |
| Local directory | syft dir:./my-project (or syft ./my-project) |
| File | syft file:./pom.xml |
| Singularity image | syft singularity:./image.sif |
Step 5 - Attestation pattern (cosign)
For supply-chain integrity, attach the SBOM to the container image via Sigstore cosign:
# Generate SBOM
syft my-image:1.0 -o cyclonedx-json=sbom.json
# Sign + attach to image (Sigstore)
cosign attest --predicate sbom.json --type cyclonedx my-image:1.0
# Verify
cosign verify-attestation --type cyclonedx my-image:1.0The attestation lives alongside the image in the registry; downstream consumers can verify provenance + retrieve the SBOM.
Step 6 - False-positive triage analogue
Syft generates inventories, not findings - there's no FP triage per se. The analogue here is inventory accuracy: ensuring Syft correctly identifies all components.
| Mechanism | Use |
|---|---|
--exclude=PATH_PATTERN | Skip directories from scan (vendor / generated) |
--catalogers=CATALOGER | Restrict to specific catalogers (e.g., npm, python) |
--source-name=NAME / --source-version=VERSION | Override SBOM-level metadata |
--platform=linux/amd64 | Target specific platform for multi-arch images |
Inventory accuracy validation:
# Compare two SBOMs (e.g., before vs after a build change)
syft image:1.0 -o syft-json=v1-sbom.json
syft image:1.1 -o syft-json=v1.1-sbom.json
diff <(jq -S . v1-sbom.json) <(jq -S . v1.1-sbom.json)If Syft misses a component (false negative on inventory), the downstream vuln scan misses any CVEs against that component. Periodic accuracy validation against known dependencies catches this.
Step 7 - CI integration
jobs:
sbom:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: anchore/sbom-action@v0
with:
path: ./
format: cyclonedx-json
output-file: sbom.cyclonedx.json
- uses: anchore/sbom-action@v0
with:
path: ./
format: spdx-json
output-file: sbom.spdx.json
- uses: actions/upload-artifact@v4
with:
name: sboms
path: sbom.*.jsonThe anchore/sbom-action GHA wraps Syft + handles GitHub dependency-graph submission automatically when format: github-json.
Step 8 - Composition with sister tools
| Sister tool | Use |
|---|---|
grype-scanning | SBOM-driven vuln scanning (grype sbom:./sbom.json) |
cyclonedx-format | Reference for CycloneDX schema + spec compliance |
spdx-format | Reference for SPDX schema + spec compliance |
trivy-image | Alternative scanner (built-in SBOM gen + scan in one pass) |
osv-scanner | Cross-plugin: also accepts SBOM input |
Anti-patterns
| Anti-pattern | Why it fails | Fix |
|---|---|---|
| Generate SBOM only at release time | Misses build-time inventory differences | Generate per CI build + attest |
| Use single format only | Different consumers need different formats | Generate both CycloneDX + SPDX (Step 2) |
| Skip platform targeting on multi-arch images | Misses platform-specific deps | --platform=linux/amd64 (Step 6) |
| Generate SBOM but don't attest / sign | Provenance unverifiable downstream | Cosign attest pattern (Step 5) |
| Trust Syft inventory without validation | Misses components → misses CVEs | Periodic accuracy check (Step 6) |