Introduction to Syft and SBOMs
A Software Bill of Materials (SBOM) is a formal, machine-readable inventory of software components and dependencies, including their versions, licenses, and security metadata. As software supply chain attacks grow more sophisticated, SBOMs have become a foundational security practice, mandated by initiatives like the U.S. Executive Order 14028 and frameworks such as SLSA and NIST SSDF.
Syft is an open-source CLI tool and Go library created by Anchore that generates SBOMs from container images, filesystems, archives, and source repositories. It supports multiple output formats (SPDX, CycloneDX, Syft JSON) and detects packages across dozens of ecosystems including npm, pip, Maven, Go modules, Alpine apk, Debian dpkg, and RPM.
Why SBOMs Matter
- Vulnerability detection: Pair SBOMs with tools like Grype to scan dependencies against CVE databases.
- License compliance: Track transitive licenses to avoid legal exposure.
- Supply chain transparency: Provide auditable records of what's inside your artifacts.
- Incident response: Quickly identify whether a newly disclosed CVE affects your deployed software.
- Regulatory compliance: Meet requirements from government and industry standards.
Installing Syft
Syft ships as a single static binary, making installation straightforward across platforms.
macOS
brew install syft
Linux (curl install)
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
Windows (Scoop)
scoop install syft
Docker
docker pull anchore/syft:latest
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock anchore/syft:latest <image>
Verify the installation:
syft version
Basic SBOM Generation
The simplest invocation analyzes a container image and prints an SBOM to stdout.
Analyzing a Container Image
syft nginx:latest
By default, Syft outputs a human-readable table. For machine consumption, specify an output format with the -o flag.
Generating SPDX JSON
syft nginx:latest -o spdx-json > nginx.spdx.json
Generating CycloneDX XML
syft nginx:latest -o cyclonedx-xml > nginx.cyclonedx.xml
Supported Output Formats
syft-jsonโ Syft's native, detailed JSON format (default for-o json)spdx-json,spdx-xml,spdx-tagvalueโ SPDX 2.3cyclonedx-json,cyclonedx-xmlโ CycloneDX 1.4/1.5tableโ human-readable table (default)github-jsonโ GitHub dependency snapshot format
Analyzing Different Sources
Syft is not limited to container images. It supports several source types.
Filesystem Analysis
Scan a local directory, useful for source trees or extracted artifacts:
syft dir:./my-project -o spdx-json > project.spdx.json
OCI Archives and Tarballs
syft oci-archive:./image.tar -o cyclonedx-json > image.cdx.json
syft docker-archive:./image.tar -o json > image.syft.json
Source Repositories
Syft can detect lockfiles and manifests directly from a git checkout:
syft dir:./repo --scope all-layers -o table
Configuration with syft.yaml
For repeatable, team-shared configurations, use a config file. Syft searches for .syft.yaml in the current directory, home directory, and SYFT_CONFIG_PATH.
# .syft.yaml
output:
- format: spdx-json
file: ./sbom.spdx.json
# Restrict which package ecosystems are detected
package:
catalogers:
- python
- npm
- go-module
- dpkg
# Include only packages with these licenses in the report
license:
include:
- MIT
- Apache-2.0
# Exclude paths from analysis
exclude:
paths:
- "**/test/**"
- "**/.git/**"
Run with the config:
syft dir:./my-app -c .syft.yaml
Using Syft as a Go Library
Beyond the CLI, Syft exposes a Go API for embedding SBOM generation into custom tooling. This is useful for building internal security platforms or custom pipelines.
package main
import (
"fmt"
"log"
"github.com/anchore/syft/syft"
"github.com/anchore/syft/syft/sbom"
"github.com/anchore/syft/syft/source"
)
func main() {
// Configure the source to analyze
src, cleanup, err := source.New("dir:./my-project", nil, source.DefaultConfig())
if err != nil {
log.Fatalf("failed to create source: %v", err)
}
defer cleanup()
// Generate the SBOM
s, err := syft.CreateSBOM(src, nil, nil)
if err != nil {
log.Fatalf("failed to create SBOM: %v", err)
}
// Print a summary
fmt.Printf("SBOM contains %d artifacts\n", len(s.Artifacts.Packages.Sorted()))
// Serialize to Syft JSON
jsonBytes, err := syft.Encode(*s, sbom.JSONFormat)
if err != nil {
log.Fatalf("failed to encode SBOM: %v", err)
}
fmt.Println(string(jsonBytes))
}
Run the program:
go mod init sbom-demo
go get github.com/anchore/syft
go run main.go
Integrating Syft into CI/CD
GitHub Actions
The official anchore/sbom-action generates an SBOM and optionally uploads it to GitHub's dependency graph or Anchore Enterprise.
name: Generate SBOM
on:
push:
branches: [main]
pull_request:
jobs:
sbom:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Generate SBOM
uses: anchore/sbom-action@v0
with:
image: my-registry/app:latest
format: spdx-json
output-file: sbom.spdx.json
artifact-name: app-sbom
- name: Scan SBOM for vulnerabilities
uses: anchore/scan-action@v3
with:
sbom: sbom.spdx.json
fail-build: true
severity-cutoff: high
GitLab CI
generate-sbom:
image: anchore/syft:latest
script:
- syft $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA -o spdx-json -o sbom.spdx.json
artifacts:
paths:
- sbom.spdx.json
reports:
cyclonedx: sbom.spdx.json
Jenkins Pipeline
pipeline {
agent any
stages {
stage('SBOM') {
steps {
sh 'syft my-image:latest -o spdx-json > sbom.spdx.json'
archiveArtifacts artifacts: 'sbom.spdx.json', fingerprint: true
}
}
}
}
Best Practices
- Generate SBOMs at build time, not deploy time. Capture the exact dependency state when the artifact was produced. Store the SBOM alongside the artifact in your registry or artifact store.
- Use a standard format. Prefer SPDX or CycloneDX for interoperability with downstream tools. Reserve Syft JSON for internal tooling that needs richer metadata.
- Pin Syft versions in CI. Avoid
latesttags to ensure reproducible scans. Use semantic version pins likeanchore/syft:v1.9.0. - Pair with Grype for vulnerability scanning. Syft produces the inventory; Grype consumes it to find CVEs. This separation of concerns keeps pipelines modular.
- Scope catalogers appropriately. Disable unused ecosystems in
syft.yamlto reduce scan time and noise in large images. - Sign and verify SBOMs. Use cosign or similar tools to attach signatures to SBOMs stored in OCI registries, ensuring tamper resistance.
- Automate drift detection. Compare SBOMs between builds to detect unexpected dependency additions, which can signal a compromised dependency or insider threat.
- Store SBOMs long-term. Retain SBOMs for the lifetime of deployed software plus a compliance-mandated retention window, so you can respond to future CVE disclosures.
Conclusion
Syft provides a fast, flexible, and standards-compliant way to generate SBOMs across containers, filesystems, and source repositories. By integrating Syft into your build pipelines and pairing it with vulnerability scanners like Grype, you establish a transparent, auditable software supply chain that strengthens security posture and satisfies emerging regulatory requirements. Start with a simple syft <image> -o spdx-json in your CI, then layer in configuration, signing, and drift detection as your program matures. The investment pays off the first time a critical CVE is disclosed and you can answer "are we affected?" in seconds rather than days.