On 15 September 2026 the Swift project released Swift 6.4. Among its package manager changes is SE-0509: Swift Package Manager can now generate software bills of materials in CycloneDX or SPDX format, either as part of swift build or from a new swift package generate-sbom subcommand.
Until now, Swift teams that needed an SBOM for a customer, a regulator or their own vulnerability tracking had to use third-party tools that parse Package.resolved. Having it in the toolchain means the SBOM comes from the same dependency graph the build used.
What's affected
Swift 6.4 and later toolchains. Nothing changes unless you ask for an SBOM.
Formats. cyclonedx (or cyclonedx1) maps to CycloneDX 1.7. spdx (or spdx3) maps to SPDX 3.0. Output is JSON only.
What goes in. Each component gets its type (application or library), name, version, Package URL, source repository URL and commit SHA, entity type (package or product) and scope (required or test). Dependencies cover package to package, package to product, and product to product relationships. Metadata records the SwiftPM version, timestamp and spec version.
Build graph or package graph. With --build-system swiftbuild, only components and dependencies actually used in the build are included. Without it, everything in the resolved package graph is included and SwiftPM warns that it used the package graph only. The generate-sbom subcommand always works from the module graph and warns accordingly.
What's not there yet. The proposal lists these as future work: license detection, file hashes, signing, per-target SBOMs, XML or YAML output, and merging SBOMs. SDKs, frameworks, precompiled headers and vendored binaries aren't included.
How to check if you're exposed
Here, "exposed" means shipping Swift software without an inventory you can hand to someone. Start by checking the toolchain:
swift --version
If it reports 6.4 or later, generate a first SBOM from the package graph without building:
swift package generate-sbom --sbom-spec cyclonedx
For an SBOM that reflects what was actually compiled, generate it during the build:
swift build --build-system swiftbuild --sbom-spec cyclonedx --sbom-spec spdx \
--sbom-output-dir ./sbom
Then look at what you got. List the CycloneDX components and confirm every dependency you expect is there with a Package URL:
ls sbom/
for f in sbom/*.json; do
jq -r 'select(.bomFormat == "CycloneDX") | .components[] | "\(.name) \(.version) \(.purl)"' "$f"
done
SwiftPM doesn't overwrite earlier SBOMs; it appends a timestamp to each file name, so clear the directory between runs if you only want the latest. Anything missing is a gap to note, especially binary targets and vendored code, which the proposal says aren't covered.
What to do now
- Add SBOM generation to release builds. Use the build-integrated form so the SBOM matches the build:
Or set it through the environment in CI:swift build -c release --build-system swiftbuild --sbom-spec cyclonedx --sbom-output-dir ./sbomSWIFTPM_BUILD_SBOM_SPEC=cyclonedxandSWIFTPM_BUILD_SBOM_OUTPUT_DIR=./sbom. - Decide whether a failed SBOM should fail the build. By default it does.
--sbom-warning-onlymakes it a warning, which is fine while you adopt it but worth removing once it's stable. - Keep
Package.resolvedcurrent. Forgenerate-sbom,--disable-automatic-resolutionmakes the command fail when the resolved file is out of date, so the SBOM can't drift from the lockfile. - Fill the known gaps yourself. List XCFrameworks, binary targets and vendored code separately, and add license data from another tool until SwiftPM supports it.
- Feed the SBOM to vulnerability tracking. A CycloneDX file with Package URLs can be imported by most SCA tools and matched against advisories.
- Don't run with
--target. The proposal says--sbom-speccan't be combined with it and the build will error. Use--productto scope instead.
Why it matters
SBOM requests now arrive from customers and through procurement rules, and for many ecosystems the answer has been "we'll use a third-party tool." Native generation means the SBOM is produced by the component that resolves dependencies, which removes a whole class of parsing mismatches.
It also moves Swift closer to the inventory-first model other ecosystems are adopting. An inventory is what turns a new advisory into a quick question with a quick answer: do we ship that version, and where? The missing pieces, especially hashes and licenses, matter for some compliance uses, so treat Swift 6.4's SBOM as a solid start rather than the whole job.
Try it yourself
Generate both formats for one Swift package, once with swift package generate-sbom and once with swift build --build-system swiftbuild. Compare the component counts. Any difference shows packages that are resolved but not built, which is useful to know when you decide what to report.
Click through it at your own pace, or open it full screen.
The free scan at gold.safeguard.sh/scan accepts CycloneDX and SPDX SBOMs, runs in your browser without a login, and keeps the file on your machine. It handles up to 100 dependencies per scan.
Quick check
Which CycloneDX and SPDX versions does SwiftPM in Swift 6.4 produce?
CycloneDX 1.7 and SPDX 3.0, in JSON.
Does the SwiftPM SBOM include license information or file hashes?
Not yet. SE-0509 lists license detection, hashes and signing as future work.
Why might swift build with swiftbuild produce fewer components than generate-sbom?
With the Swift Build backend, only components and dependencies used in the build are included. The subcommand uses the full resolved package graph.