anchore/syft: generating an SBOM from a container image or a filesystem
CLI tool and library for generating a Software Bill of Materials from container images and filesystems
At a glance
- What is it?
- Syft is a Go CLI and library that catalogs packages inside container images, directories and archives and emits CycloneDX, SPDX or its own JSON. It is the inventory half of a two-tool workflow with Grype, and the split matters when you decide what to adopt.
- Who is it for?
- Adopt Syft if you need a package inventory step that is separate from vulnerability matching, and you want the same tool to read a Docker image, a directory and an archive. Do not adopt it expecting it to tell you which packages are vulnerable: that is Grype's job, and the README frames the two as a pair.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What Syft produces and who needs it
Syft answers one question: what is installed in this thing? Point it at a container image, a filesystem path, or an archive, and it enumerates the packages it can identify along with the metadata each ecosystem exposes. The README describes it as "a CLI tool and Go library for generating a Software Bill of Materials (SBOM) from container images and filesystems" and adds that it is "exceptional for vulnerability detection when used with a scanner like Grype."
The audience is narrow but real. Platform and security engineers who have to produce an inventory artifact for a build, an audit, or a registry. Supply chain teams that need a machine-readable list rather than a human reading a Dockerfile. Go developers who want the same capability inside their own program, since the repository ships a library alongside the binary, and examples/ contains runnable programs for creating an SBOM, decoding one, selecting catalogers, and pulling a source from a registry.
The important framing is that Syft does not scan for vulnerabilities. It produces the inventory that a scanner consumes. If your goal is "tell me which CVEs are in this image," Syft alone will not do it, and the README is explicit about the pairing.
How the cataloging actually works
The repository layout tells most of the story. cmd/ holds the entry point, syft/ holds the application packages, internal/ holds implementation detail, and schema/ holds the JSON schema for the native output. The go.mod file shows a dependency on github.com/anchore/stereoscope, the image-handling library, plus per-ecosystem parsers: go-rpmdb for RPM databases, go-macholibre for Mach-O and universal binaries, go-pep440-version for Python version semantics, and a CycloneDX Go library for that output format. That dependency list is the mechanism in miniature: Syft is a set of readers, one per package database or manifest format, wrapped in a common model.
The data flow is source, then catalog, then format. A source is resolved from the argument you pass (an image reference, a directory, an archive, or a registry), the catalogers run over the resulting file tree, and a presenter serializes the result. Because the source is abstracted, the same command shape works across targets, which is why the README can show `syft alpine:latest` and `syft ./my-project` side by side.
The cataloger set is the part worth understanding before you trust output. Different ecosystems store their inventory differently: some in a database file, some in a lockfile, some only as a manifest. Syft supports what the docs call dozens of ecosystems, and the examples/select_catalogers/ example exists precisely because you can restrict which ones run. If your image contains a package manager Syft has no cataloger for, that package is simply absent from the SBOM, and absence is indistinguishable from "not installed" unless you know the coverage.
Installing Syft and reading your first SBOM
The README gives a one-line installer that downloads a release and places the binary. It writes to /usr/local/bin by default, which is why it needs sudo.
curl -sSfL https://get.anchore.io/syft | sudo sh -s -- -b /usr/local/binThe same section points at the installation docs for Homebrew, Docker, Scoop, Chocolatey and Nix, so the shell script is a convenience rather than the only route. The repository also contains install.sh at the top level, which is what the hosted script serves.
Once installed, the first useful command is the plain one. Passing an image reference prints the package list to the terminal in a human-readable form.
syft alpine:latestFor anything you intend to keep, ask for a specific format. The README's examples use -o with a format name, and multiple outputs can be written to files in a single run.
syft alpine:latest -o spdx-json=./spdx.json -o cyclonedx-json=./cdx.jsonWhat you get back is one document per format, each containing the packages Syft identified. CycloneDX and SPDX are the two interchange formats the README highlights, alongside Syft's own JSON. The docs also cover converting between SBOM formats, so a pipeline that standardizes on one format can still accept another as input.
For a directory rather than an image, the command is the same with a path. This is the fastest way to see whether Syft recognizes your language ecosystem before you point it at a registry.
syft ./my-projectWhere Syft stops being the right tool
The clearest boundary is vulnerability data. Syft produces an inventory; it does not know which of those packages have known CVEs. The README's own sentence about Grype is a statement of scope, not a marketing pairing. If your requirement is a pass/fail gate on vulnerable dependencies, Syft is a component of that pipeline, not the pipeline.
The second boundary is coverage confidence. Syft detects packages by reading the artifacts each ecosystem leaves behind. A statically linked binary with no accompanying manifest, a vendored library copied into a source tree without a lockfile, or a package installed by a manager Syft has no cataloger for will not appear. The README links to a list of supported ecosystems but does not promise completeness, and no SBOM tool can. The practical consequence is that an empty or short SBOM should be treated as a signal to investigate, not as proof of a clean image.
The third is that this is a Go project built and released as a binary. The Makefile is a thin wrapper that runs `go run -C .make .`, and go.mod pins Go 1.26.3, so building from source assumes a matching toolchain. If you are not prepared to track release binaries or a Go toolchain, the install path is the deciding factor rather than the feature set.
Finally, the README does not document rollback behavior, nor does it describe what happens when a scan target is partially unreadable. Treat those as unknowns to test rather than documented guarantees.
Syft compared with Trivy's combined scanner
The obvious alternative for many teams is a scanner that does inventory and vulnerability matching in one binary. Trivy is the common example, and the difference is architectural rather than cosmetic. Trivy resolves the package list internally and immediately joins it against a vulnerability database, so a single command yields findings. Syft deliberately splits those phases: it emits a durable artifact, and Grype reads that artifact later.
That split has consequences in both directions. A stored SBOM can be re-scanned against a newer vulnerability database without rebuilding or re-pulling the image, which matters when a CVE lands months after a release. It can also be attached as an attestation, and Syft supports creating signed SBOM attestations following the in-toto specification. A combined scanner gives you an answer immediately but typically does not leave behind an inventory you can re-interrogate.
The cost of the split is operational: two tools, two versions to track, and a storage decision about where SBOMs live. Syft's own output formats make the handoff cheap, since CycloneDX and SPDX are the interchange formats Grype and other scanners consume. If your team has no place to store artifacts and no appetite for a second binary, the combined approach is simpler and Syft is the wrong shape.
Maintenance, releases and the Apache-2.0 terms
The repository is not archived, and the most recent push recorded is 2026-09-18, three days before the release v1.52.0 on 2026-09-17. Before that, v1.51.1 landed on 2026-08-27 and v1.51.0 on 2026-08-10. That cadence, roughly a minor release every few weeks with patch releases between, is the upgrade cost you should budget for. Syft is a binary you install, so upgrading means replacing the binary or the container image tag; there is no server component to migrate and no database schema of your own to change.
The compatibility surface that matters is the output schema, not the CLI. schema/ holds the JSON schema for Syft's native format, and the docs publish a versioned JSON schema reference. If a downstream consumer parses Syft JSON directly, pin the version and check the schema before upgrading. Consumers that read CycloneDX or SPDX are insulated from Syft's internal model changes, which is an argument for choosing an interchange format for anything long-lived.
Licensing: the repository states Syft is released under the Apache-2.0 License, and development is sponsored by Anchore. The README also notes the logo is CC BY 4.0, which is a separate asset licence and does not affect the code. Apache-2.0 is a permissive licence with an explicit patent grant. This is a description of what the repository says, not legal advice; if you redistribute Syft inside a product, have counsel read the licence text and any NOTICE requirements rather than relying on a summary.
Editorial conclusion
Adopt Syft if you need a package inventory step that is separate from vulnerability matching, and you want the same tool to read a Docker image, a directory and an archive. Do not adopt it expecting it to tell you which packages are vulnerable: that is Grype's job, and the README frames the two as a pair. Before rolling it out, verify two things yourself: which catalogers fire on your base images (the docs list the supported ecosystems, but not which one wins on a given layer) and whether your chosen output format carries the fields your downstream consumer reads. Start with syft <image> -o cyclonedx-json to stdout and inspect the result before wiring it into a pipeline.
Frequently asked questions
What is Syft used for?
Syft generates a Software Bill of Materials from container images, filesystems and archives. The README describes it as a CLI tool and Go library, and notes it works with a scanner like Grype for vulnerability detection.
How do I use Syft to generate an SBOM?
Run syft against a target and name one or more output formats with -o. The README shows syft <image> -o cyclonedx-json for stdout, and syft <image> -o spdx-json=./spdx.json -o cyclonedx-json=./cdx.json to write two files in one run.
What is anchore/syft?
It is the Anchore-maintained open source project that produces SBOMs from container images and filesystems, released under the Apache-2.0 License with development sponsored by Anchore. It ships both a CLI and a Go library.
What is the relationship between anchore/syft and Grype?
The README states Syft is exceptional for vulnerability detection when used with a scanner like Grype. Syft produces the inventory; Grype consumes it. They are separate tools with separate installs.
What is Anchore Grype?
The README points to Grype as the scanner that pairs with Syft, and Syft's documentation covers using the two together for vulnerability detection. The README does not describe Grype's internals.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/anchore-syft)