File: README.md
Syft
A CLI tool and Go library for generating a Software Bill of Materials (SBOM) from container images and filesystems. Exceptional for vulnerability detection when used with a scanner like Grype.
Features
- Generates SBOMs for container images, filesystems, archives (see the docs for a full list of supported scan targets)
- Supports dozens of packaging ecosystems (e.g. Alpine (apk), Debian (dpkg), RPM, Go, Python, Java, JavaScript, Ruby, Rust, PHP, .NET, and many more)
- Supports OCI, Docker, Singularity, and more image formats
- Works seamlessly with Grype for vulnerability scanning
- Multiple output formats (CycloneDX, SPDX, Syft JSON, and more) including the ability to convert between SBOM formats
- Create signed SBOM attestations using the in-toto specification
[!TIP]
New to Syft? Check out the Getting Started guide for a walkthrough!
Installation
The quickest way to get up and going:
curl -sSfL https://get.anchore.io/syft | sudo sh -s -- -b /usr/local/bin[!TIP]
See Installation docs for more ways to get Syft, including Homebrew, Docker, Scoop, Chocolatey, Nix, and more!
The basics
See the packages within a container image or directory:
# container image
syft alpine:latest
# directory
syft ./my-projectTo get an SBOM, specify one or more output formats:
# SBOM to stdout
syft -o cyclonedx-json
# Multiple SBOMs to files
syft -o spdx-json=./spdx.json -o cyclonedx-json=./cdx.json[!TIP]
Check out the Getting Started guide to explore all of the capabilities and features.Want to know all of the ins-and-outs of Syft? Check out the CLI docs, configuration docs, and JSON schema.
Contributing
We encourage users to help make these tools better by submitting issues when you find a bug or want a new feature.
Check out our contributing overview and developer-specific documentation if you are interested in providing code contributions.
Syft development is sponsored by Anchore, and is released under the Apache-2.0 License.
The Syft logo by Anchore is licensed under CC BY 4.0
For commercial support options with Syft or Grype, please contact Anchore.
Come talk to us!
The Syft Team holds regular community meetings online. All are welcome to join to bring topics for discussion.
- Check the calendar for the next meeting date.
- Add items to the agenda (join this group for write access to the agenda)
- See you there!
File: examples/README.md
Syft API Examples
This directory contains examples of how to use the Syft API.
create_simple_sbom: Create a simple SBOM from scratchcreate_custom_sbom: Create an SBOM using as much custom configuration as possible, including a custom cataloger implementationdecode_sbom: Take an existing SBOM file (of arbitrary format) and decode it into a Syft SBOM objectselect_catalogers: Example demonstrating how to select specific catalogers to runsource_detection: Shows how to detect what to catalog automatically from a user string (e.g. container image vs directory)source_from_image: Construct a source from only a container imagesource_from_registry: Construct a source directly from a container registry
You can run any of these examples from this directory with:
go run ./DIRECTORY_NAMEFile: internal/cache/README.md
Caching
All caches are created from a global manager. By default this is a bypassedCache, which performs no caching.
One benefit of this is that tests don't need to worry about caching causing issues unless they explicitly need
to test the cache and can opt-in using the cache.TestCache(t) helper.
Syft sets a filesystemCache when the cache options are loaded.
When using the filesystemCache all items are stored on disk under a root directory, generally in the form of:
<rootDir>/<named-cache>/<data-version>/path/to/dataUsing the cache
The easiest and preferred method to use the cache is a cache.Resolver, which automatically creates a <data-version>
based on the structure of the provided type.
If the structure changes in any way it will end up with a new version key and all will re populate this new key,
ignoring cached values from older, different versions.
The resolver will store items using the json package to serialize/deserialize values, so to save space
it is encouraged to use omitempty. For example:
type myCacheItem struct {
Name string `json:"name",omitempty`
}It is possible to use core types such as pkg.Package as long as they support the standard json serialization,
but this is discouraged in order to decouple changes to them from affecting the information stored in the cache.
To get a cache for this type:
resolver := cache.GetResolver[myCacheItem]("myCacheName", "v1")Using the resolver is a single call, which manages checking for items in the cache, expiry times,
and if not found invoking the callback to populate the cache and return a value:
data := resolver.Resolve("some/cache/key", func() (myCacheItem, error) {
// do things to return a myCacheItem or error
})If it is common that checking for an item will result in errors, and you do not want to re-run the resolve function
when errors are encountered, instead of using GetResolver, you can use GetResolverCachingErrors, which is useful
for things such as resolving artifacts over a network, where a number of them will not be resolved, and you do not want
to continue to have the expense of running the network resolution. This should be used when it is acceptable a network
outage and cached errors is an acceptable risk.
An example can be seen in the golang cataloger fetching remote licenses.
File: schema/json/README.md
JSON Schema
This is the JSON schema for output from the JSON presenters (syft packages -o json). The required inputs for defining the JSON schema are as follows:
- the value of
internal.JSONSchemaVersionthat governs the schema filename - the
Documentstruct definition withingithub.com/anchore/syft/syft/formats/syftjson/model/document.gothat governs the overall document shape - generated
AllTypes()helper function within thesyft/internal/sourcemetadataandsyft/internal/packagemetadatapackages
With regard to testing the JSON schema, integration test cases provided by the developer are used as examples to validate that JSON output from Syft is always valid relative to the schema/json/schema-$VERSION.json file.
Versioning
Versioning the JSON schema must be done manually by changing the JSONSchemaVersion constant within internal/constants.go.
This schema is being versioned based off of the "SchemaVer" guidelines, which slightly diverges from Semantic Versioning to tailor for the purposes of data models.
Given a version number format MODEL.REVISION.ADDITION:
MODEL: increment when you make a breaking schema change which will prevent interaction with any historical dataREVISION: increment when you make a schema change which may prevent interaction with some historical dataADDITION: increment when you make a schema change that is compatible with all historical data
Adding a New `pkg.*Metadata` Type
When adding a new pkg.*Metadata that is assigned to the pkg.Package.Metadata struct field you must add a test case to cmd/syft/internal/test/integration/catalog_packages_cases_test.go that exercises the new package type with the new metadata.
Additionally it is important to generate a new JSON schema since the pkg.Package.Metadata field is covered by the schema.
Generating a New Schema
Create the new schema by running make generate-json-schema from the root of the repo:
- If there is not an existing schema for the given version, then the new schema file will be written to
schema/json/schema-$VERSION.json - If there is an existing schema for the given version and the new schema matches the existing schema, no action is taken
- If there is an existing schema for the given version and the new schema does not match the existing schema, an error is shown indicating to increment the version appropriately (see the "Versioning" section)
Note: never delete a JSON schema and never change an existing JSON schema once it has been published in a release! Only add new schemas with a newly incremented version. All previous schema files must be stored in the schema/json/ directory.
Exception: `description`-only corrections
A published schema may be amended in place for one narrow case: the change touches only description text and leaves the data shape identical. Descriptions are documentation carried alongside the schema rather than constraints a validator evaluates, so correcting one cannot invalidate a document that already validated against that version. Minting a new version instead would leave the old one permanently describing the tool incorrectly, and spend a version number on no semantic change.
This applies when every one of the following holds:
- the only differences are
descriptionvalues - no field, type, enum,
requiredentry, or$refis added, removed, or altered - the
$idversion is unchanged
Anything else, including adding a field that happens to be optional, is a schema change and needs a version bump per the "Versioning" section above.
The generator blocks an in-place edit by design, since it refuses to overwrite a file that differs from what it would produce. To amend one, delete the schema file and regenerate so it is rewritten from the current Go doc comments:
rm schema/json/schema-$VERSION.json
make generate-json-schemaThe result is byte-identical to what the generator produces, so do not hand-edit the JSON. Re-running make generate-json-schema afterwards should report No change to the existing schema!, and make check-json-schema-drift should pass. Confirm with git diff that the only changes are the intended description lines.
File: schema/cyclonedx/README.md
CycloneDX Schemas
syft generates a CycloneDX Bom output. We want to be able to validate the CycloneDX schemas
(and dependent schemas) against generated syft output. The best way to do this is with xmllint,
however, this tool does not know how to deal with references from HTTP, only the local filesystem.
For this reason we've included a copy of all schemas needed to validate syft output, modified
to reference local copies of dependent schemas.
You can get the latest schemas from the CycloneDX specifications repo.
When the spec version is bumped an approach to determining prior modifications is to compare the
prior spec version (e.g. if updating to 1.7, compare the files in this directory against the 1.6
equivalents).
One can also update the schemas and observe the errors in order to make the necessary updates.
At the time of writing, the cyclonedx.xsd needed modifications to link to the local spdx.xsd,
and also to change the minOccurs for a license tag to 0. (The json schema does not require
modification for the generated file to lint properly, but can simply be copy/pasted).
File: syft/pkg/cataloger/golang/internal/README.md
xcoff
The code in this package comes from: https://github.com/golang/go/tree/master/src/internal/xcoff -- it was copied over to add support for xcoff binaries. Golang keeps this package as internal, forbidding its external use.