SBOM
A hijacked package is usually a dependency, not the one you asked for. So
aur-scan can emit a CycloneDX 1.5 SBOM of the entire resolved AUR dependency
tree — every package it would pull in, where each came from, and what the scan
found — as an auditable artifact you can keep, diff, or feed to other tooling.
Generating one
The SBOM is written by the tree-resolving commands, to a file you name:
aur-scan check <package> --sbom tree.cdx.json # before installing
aur-scan install <package> --sbom tree.cdx.json # race-free install + SBOM
aur-scan check --local ./mypkg --sbom tree.cdx.json # an on-disk package(The single-package scan command doesn’t emit an SBOM — there’s no tree to
describe.) The document is pretty-printed JSON; nothing goes to stdout but the
status line.
What’s inside
The top of the document is standard CycloneDX:
{
"bomFormat": "CycloneDX",
"specVersion": "1.5",
"serialNumber": "urn:uuid:…",
"metadata": {
"tools": [{ "vendor": "Kief Studio", "name": "aur-scan", "version": "2.0.0" }],
"component": { "type": "application", "name": "<root package>" }
}
}Each package in the resolved tree is a component, keyed by an alpm package
URL so it lines up with Arch tooling:
pkg:alpm/arch/<name>@<version>?repository=aur # an AUR package
pkg:alpm/arch/<name>?repository=repo # an official-repo dependencyEvery component carries aur-scan:* properties that a generic SBOM can’t express:
| Property | Meaning |
|---|---|
aur-scan:source | aur or repo |
aur-scan:depth | distance from the package you asked for |
aur-scan:orphaned | no maintainer — the prime hijack target |
aur-scan:findings | per-package critical/high counts |
aur-scan:opaque | this package fetches/executes external code — the SBOM is incomplete past this node |
aur-scan:remote-source | the external URLs it pulls from |
The document also includes a dependencies graph (which package depends on which)
and a vulnerabilities array — each scan finding expressed as a CycloneDX
vulnerability, rated by severity and linked to the component it affects.
The opaque boundary, in the SBOM
When a package fetches and runs code from elsewhere, the scanner marks it opaque
and does not follow the link — so the SBOM honestly records “coverage stops
here” rather than pretending to enumerate something it refused to execute. That
aur-scan:opaque marker plus the remote-source URL is the SBOM telling you
exactly where its visibility ends and why. See How it works for
the static-only guarantee behind that.