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 dependency

Every component carries aur-scan:* properties that a generic SBOM can’t express:

PropertyMeaning
aur-scan:sourceaur or repo
aur-scan:depthdistance from the package you asked for
aur-scan:orphanedno maintainer — the prime hijack target
aur-scan:findingsper-package critical/high counts
aur-scan:opaquethis package fetches/executes external code — the SBOM is incomplete past this node
aur-scan:remote-sourcethe 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.