Scanning Container Images
kunnus sbom container generates an SBOM for a container image and records, for every component, which image layer introduced it. Alias: kunnus sbom image.
kunnus sbom container alpine:3.20 --output alpine.cdx.json # registry pull
kunnus sbom container ./image.tar --output image.cdx.json # docker save / OCI tarball
kunnus sbom container myapp:dev --source docker # local docker daemonImage sources
--source controls where the image comes from: auto (default — kunnus picks based on the argument), remote (pull from a registry), tarball (a docker-save or OCI archive on disk), or docker (the local daemon). A tarball scan is fully offline; a remote reference is the one case where this mode touches the network.
Per-layer attribution
Every component carries kunnus:layer:* properties: the index and DiffID of the layer that introduced it, the Dockerfile instruction that produced that layer, and whether it belongs to a detected base image. A package present in several layers lists all of them. That answers the two questions auditors actually ask: did this come from our build or from the base image, and which build step added it?
What container scans include
Container scans run the installed-state extractors — OS packages of every supported Linux family, installed language packages (wheels, gems, JARs, node_modules, Go/.NET binaries), and the non-packaged-binary classifier. Declared-dependency files like a stray package.json are deliberately not treated as installed software. The kernel extractors are host-only and never run here: a container uses the host's kernel, so claiming one in its SBOM would be wrong.
Distroless and chiselled images
Chiselled Ubuntu images (Canonical's distroless variant) have no dpkg database — their package record is the chisel manifest at var/lib/chisel/manifest.wall, which kunnus reads as its own distro family. On top of the packages themselves, the manifest's per-package SHA-256 digests are recovered and attached as component hashes, and the DEP-5 copyright files each package's copyright slice ships supply the licences. A distroless image therefore produces a fully populated SBOM rather than an empty one.
A registry reference also carries its own identity: ghcr.io/acme/app:v1.2.3 keys the SBOM's serial number by repository path with the tag as the component version, so successive builds pushed to one tag form a document series without any extra flags. Tarball scans have no such identity — see the SBOM identity guide.