Verified10 commandsAI-assisted

Syft

.md

Verified against Syft 1.32.0, flags verified via `syft --help` run locally, 2026-08-29 · official docs

What it is and where it fits 🎯#

Syft generates a Software Bill of Materials (SBOM) from a container image or filesystem — every package, its version, and where it came from. This is the "what's actually in this artifact, right now" half of supply-chain visibility; feed the output into Grype (its sibling tool), Trivy, or a continuously-updating platform like Dependency-Track to turn an inventory into a vulnerability answer. Syft itself finds nothing "bad" — it's purely descriptive, which is exactly why it's cheap to run on every single build and archive the result, rather than treating SBOM generation as an occasional audit activity.

The generate-once, scan-many pattern#

Diagram

The SBOM never goes stale about what's in the artifact — only the vulnerability data matched against it changes over time, and re-matching a stored SBOM is a cheap operation compared to re-pulling and re-scanning the original image months or years later (which may not even be possible if the image was later deleted from the registry).

Installation#

curl -sSfL https://get.anchore.io/syft | sh -s -- -b /usr/local/bin
brew install syft

syft version

Generating an SBOM#

syft scan alpine:latest                                # human-readable summary table (default)
syft scan alpine:latest -o json                         # full Syft-native JSON, all cataloging detail
syft scan alpine:latest -o cyclonedx-json > sbom.cdx.json    # industry-standard, widely consumed downstream
syft scan alpine:latest -o spdx-json > sbom.spdx.json         # the other major standard (Linux Foundation)
syft scan dir:./myproject                                # a filesystem path instead of an image
syft scan registry:myrepo/myimage:tag                    # pull directly from a registry, no daemon required

Note

CycloneDX vs SPDX — both are legitimate, widely-adopted SBOM standards; the choice usually comes down to what your downstream consumer expects. CycloneDX (OWASP-originated) tends to be favored by security-tooling ecosystems (Dependency-Track, most vuln scanners); SPDX (Linux Foundation-originated) is more common in license-compliance and legal contexts. Generating both from the same scan is cheap — Syft supports multiple -o outputs in one invocation.

Sample output shape#

Default table output (illustrative counts — actual packages depend on the scanned image):

NAME VERSION TYPE musl 1.2.4-r0 apk busybox 1.36.1-r15 apk openssl 3.1.4-r5 apk

Choosing image source explicitly#

syft scan docker:myapp:latest              # local Docker daemon
syft scan podman:myapp:latest
syft scan oci-archive:myapp.tar             # a saved OCI tarball
syft scan file:./go.sum                     # a single manifest file

Scoping and filtering#

syft scan myapp:latest --exclude './vendor/**'
syft scan myapp:latest --scope all-layers          # every layer's contents, not just the final squashed filesystem
syft scan myapp:latest --select-catalogers +sbom    # add/remove/filter which package catalogers run

Chaining into Grype#

syft scan myapp:latest -o json | grype                        # pipe an SBOM straight into a vuln scan, no re-pull needed
syft scan myapp:latest -o cyclonedx-json=sbom.json && grype sbom:sbom.json

Generating an SBOM as an attestation (for cosign)#

syft attest --output cyclonedx-json myapp:latest --key cosign.key > attestation.json
cosign attest --predicate attestation.json --type cyclonedx myapp:latest

This is where SBOM generation meets supply-chain signing (see the cosign cheat sheet): a signed attestation proves not just what's in the image, but that the SBOM itself came from your build pipeline and hasn't been tampered with after the fact.

Converting between SBOM formats#

syft convert sbom.spdx.json -o cyclonedx-json=sbom.cdx.json

Real-world scenario: archiving an SBOM per release for future-proof compliance#

A team facing an upcoming compliance audit (SOC 2, PCI-DSS) needs to answer "what open-source components were in production version 4.2.0, six months ago" — and the production image from that release may no longer even exist in the registry.

# At release time, every release:
syft scan myapp:v4.2.0 -o cyclonedx-json=releases/v4.2.0/sbom.cdx.json
git add releases/v4.2.0/sbom.cdx.json && git commit -m "SBOM for v4.2.0"

Tip

Committing the SBOM alongside the release (not just leaving it in a scanner's cache) is what makes this genuinely audit-proof. Six months later, grype sbom:releases/v4.2.0/sbom.cdx.json still works perfectly even if the container image itself was deleted from the registry to save storage cost — the SBOM is the durable record, the image doesn't need to be.

Real-world scenario: GitHub Actions CI recipe#

# .github/workflows/syft.yml
name: Generate SBOM
on:
  push:
    tags: ['v*']
jobs:
  sbom:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Build image
        run: docker build -t myapp:${{ github.ref_name }} .
      - uses: anchore/sbom-action@v0
        with:
          image: myapp:${{ github.ref_name }}
          format: cyclonedx-json
          output-file: sbom.cdx.json
      - uses: actions/upload-artifact@v4
        with:
          name: sbom-${{ github.ref_name }}
          path: sbom.cdx.json

Shell completion#

syft completion bash | sudo tee /etc/bash_completion.d/syft

Common pitfalls#

  • Treating SBOM generation as a one-time audit task rather than a per-build artifact — the value compounds over time specifically because you have one for every release, not just the current one.
  • Only generating JSON, not a standard format — Syft's native JSON is the richest format but the least portable; use CycloneDX or SPDX for anything that needs to interoperate with other tooling.
  • Scanning squashed scope on an image where a vulnerable package was removed in a later layer — the default squashed scope only sees the final filesystem state; --scope all-layers is needed to catch a package that existed in an intermediate layer (still technically present in the image's history/size) but was deleted before the final layer.

When to reach for something else#

Trivy also generates SBOMs (trivy image --format cyclonedx) from the same kind of source — a team already standardized on Trivy for vulnerability scanning may reasonably use its built-in SBOM support instead of adding Syft as a separate tool. Syft's edge is being purpose-built and maintained specifically for cataloging depth and format fidelity, which is why Trivy itself uses Syft's cataloging library internally for some of its own SBOM generation.