The AI bill of materials that shows its work.
AIROM scans filesystems, Git repositories, container images, and Kubernetes workloads. It produces an AI Bill of Materials: the models, prompts, datasets, embeddings, vector databases, and frameworks your software actually uses. Every entry records the file and line it was found at and the rule that found it, and every scan reports what it could not prove.
$pip install airom
┌──────────────────┬────────────────────────┬─────────┬─────────────┬───────┬────────────────────┬──────────┐ │ KIND │ NAME │ VERSION │ PROVIDER │ CONF │ LOCATION │ EVIDENCE │ ├──────────────────┼────────────────────────┼─────────┼─────────────┼───────┼────────────────────┼──────────┤ │ embedding-model │ text-embedding-3-large │ - │ openai │ 0.85 │ src/rag.py:6 │ 1 occ │ │ framework │ langchain │ 0.2.16 │ langchain │ 0.95 │ requirements.txt:2 │ 1 occ │ │ hosted-llm │ gpt-4.1 │ - │ openai │ 0.85 │ src/rag.py:15 │ 1 occ │ │ library │ openai │ 1.51.0 │ openai │ 0.985 │ requirements.txt:3 │ 2 occ │ │ local-model-file │ tiny.gguf │ - │ local │ 0.95 │ models/tiny.gguf │ 1 occ │ │ prompt │ system.txt │ - │ - │ 0.8 │ prompts/system.txt │ 1 occ │ │ rag-pipeline │ rag-pipeline │ - │ - │ 0.6 │ src/rag.py:6 │ 1 occ │ │ vector-db │ chroma │ 0.5.5 │ chroma │ 0.985 │ requirements.txt:4 │ 3 occ │ └──────────────────┴────────────────────────┴─────────┴─────────────┴───────┴────────────────────┴──────────┘
An inventory says what. Evidence says why.
“Your AIBOM says this service uses gpt-4.1. Why? Where?”
Most tools cannot answer that. They report a model you registered somewhere, or they never read your code. AIROM records how it found each component, and where. Every component carries four things:
- Occurrences
- Every place the component was seen. Each records
file:line, the matched snippet, and the enclosing function or class where AIROM can determine it. - Detection method
- How it was found: source-code analysis, AST fingerprint, manifest analysis, binary analysis, hash comparison, config analysis, or filename.
- Confidence
- An evidence-weighted score from 0 to 1, recorded on the component and on each occurrence separately.
- Detector ID
- The rule that fired, such as
rules/openai/model-literal. Identifiers stay stable across releases, so you can audit or suppress a specific rule.
All of it is written into CycloneDX evidence.occurrences[], a field most AIBOM
tools leave empty. AIROM is equally explicit about what it does not know. A version it
cannot resolve stays empty instead of being guessed, and a model missing from the
lifecycle catalog carries no claim rather than a quiet “supported”.
Risk, vulnerabilities, and CI checks
The same scan feeds security review and pull-request gating.
Risk detection
Finds code-execution surfaces that fire when a model file is loaded: pickle imports, Keras Lambda layers, GGUF template gadgets, and unsafe torch.load calls. Findings are written as CycloneDX vulnerabilities and SARIF.
CVE overlay
Matches the AI dependencies AIROM inventoried against OSV.dev and reports real CVSS scores. The gate fails closed: under --offline it refuses to run rather than reporting zero findings.
Model lifecycle
Checks hosted models against a curated catalog of provider retirement announcements. Every entry is dated and cites the provider page it came from, and nothing is inferred from naming patterns.
No invented scoresCompliance mapping
Maps findings to NIST AI RMF and OWASP Agentic controls, emitted as CycloneDX attestations. Each control is marked met, gap, or manual, and links to the evidence behind that verdict.
Per-PR controlAIBOM diff
Reports the semantic difference between two scans, so a new model or framework surfaces in the pull request that introduced it. It refuses to gate when the two scans came from different tooling versions.
ed25519-verifiedSigned rule updates
Delivers new framework detection and updated retirement dates over an ed25519-signed channel, without shipping a new binary. Scanning never fetches rules; updates are an explicit command.
Built like a security tool
- No model execution, ever. Weights are identified by magic bytes and bounded header parsing. Nothing is loaded, deserialized, or run.
- Fuzzed parsers. Every binary header parser is fuzzed in CI and must return errors, never panic.
- No surprise network access.
--offlineasserts it globally. - Signed releases.
CGO_ENABLED=0, reproducible, checksummed, and keyless-cosign-signed.
Scan something
One command and a single static binary. No agent, no daemon, no account, no telemetry.