airom image scans a container image: it resolves the image’s squashed root filesystem and streams its files through the same detector pipeline as a directory scan.
Live registry and docker-daemon pulls are not wired up in this build. airom image ubuntu:24.04 does not reach out to a registry — it fails with a clear error. Today, supply a local image archive with --input, or point at an OCI layout directory. This page documents only what works.

What works today

A positional reference is accepted only when it is a path to one of those on disk. A reference and --input are mutually exclusive; supplying neither is a usage error.

The docker save workflow

1

Export the image to a tarball

docker save
2

Scan the tarball

Scan it — no network
3

Write the AIBOM

CycloneDX out
--input reads a saved archive and touches no network. It is the supported path for CI, air-gapped builds, and anywhere a registry pull is not on the table.

Layers are squashed

AIROM applies the image’s layers top→base with whiteout and opaque-directory resolution, exactly once, and scans the resulting effective filesystem. A file deleted by a later layer is gone; a file overwritten by a later layer is seen only in its final form.
The AIBOM answers “what’s in the final image”, not “what did each layer contribute”. There is no per-layer attribution in the output.

Bounded memory on any image size

Layer tar streams are consume-once, so each effective file’s bytes are captured during the single squash pass. That capture is strictly bounded: Memory and disk stay bounded regardless of image size. Temp files are removed when the scan finishes.

--platform

--platform <os/arch> is accepted, but it is not yet honored. A multi-arch index today resolves to the first image manifest in the index, whatever its platform. Do not rely on this flag to select an architecture.
To scan a specific architecture reliably, export that architecture yourself and scan the resulting archive:
Export one platform, then scan it

Ignore globs

--ignore works on image scans and matches against image-root paths. The .gitignore/.airomignore stacks do not apply here — an image has no ignore files to read. Only your --ignore globs filter an image walk.
Skip a vendored directory inside the image

Versions come from installed metadata

An image rarely ships the manifest it was built from. requirements.txt and pyproject.toml stay behind in the source repo; what lands in the image is site-packages. So AIROM reads the installed metadata directly — <pkg>-<version>.dist-info/METADATA (PEP 376) and <pkg>.egg-info/PKG-INFO — and that is the strongest version evidence there is. A manifest records the version that was asked for (openai>=1.0); installed metadata records the one that is there.
Each of the three libraries carries two occurrences — the import in the application code and the metadata that pins its version — folded into one component, which is why CONF reads 0.99. LOCATION shows the code site; airom scan --format json lists both. Without the metadata half, the VERSION column is -. gpt-4o-mini has no version because a hosted model has no installed metadata to read; its lifecycle is covered by the EOL overlay instead.
This is what makes the CVE overlay useful on an image. A component with no version can be listed but never matched against an advisory database, so a version-less scan reports zero vulnerabilities no matter how many the image actually has.
An installed tree holds far more than AI packages. AIROM parses every METADATA it finds and reports only the ones its AI catalog recognizes — numpy, click, and certifi are read and dropped. An AIBOM is not an SBOM. The same applies to any installed environment on disk, not just images: a docker cp’d site-packages, an unpacked PyInstaller bundle, or a container filesystem mounted for inspection. Note that .venv/ and venv/ are skipped by default, so scanning a source checkout still reads its manifest rather than its virtualenv.

Known limitations

Gzip and uncompressed layers are read. A zstd-compressed layer is recorded as an Unknown and its contents do not reach the detectors.
Files are served from a consume-once spool, so detectors that need random access get ErrNotSeekable. Streaming and header reads are unaffected.
Registry and daemon resolution is deferred. The imageDigest field of the AIBOM source block is not populated by the current pipeline.

Example

Image scan, filtered, two outputs
The output is identical to a filesystem scan — a boxed Scan Summary panel followed by the component table (see Output formats) — because AIROM scans the application source extracted from the image.
--parallel, --io-budget, --max-file-size, and --select behave the same as on a filesystem scan. See /scanning/filesystem.