Skip to content
Open source · Apache 2.0 · single static binary

Find the AI in your code, and prove it.

AIROM scans a filesystem, git repo, container image, or Kubernetes workload and generates an AI Bill of Materials — the models, prompts, datasets, embeddings, vector databases and frameworks your software actually uses — with file:line evidence behind every entry.

$ pip install airom
Quickstart GitHub

No agent, no daemon, no account, no telemetry. Weights are identified by magic bytes — never loaded, deserialized, or run.

airom scan .
┌──────────────────┬────────────────────────┬─────────┬─────────────┬───────┬────────────────────┬──────────┐
│ 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    │
└──────────────────┴────────────────────────┴─────────┴─────────────┴───────┴────────────────────┴──────────┘

Sooner or later, someone asks why

“Your AIBOM says this service uses gpt-4.1. Why? Where?”

Most tools can’t answer. They describe a model you named in a registry, or they never look at your code. AIROM is evidence-first: every component it emits carries the proof.

Occurrences
Every sighting — file:line, the matched snippet, and the enclosing function or class when known.
Detection method
Which technique found it: source-code analysis, AST fingerprint, manifest analysis, binary analysis, hash comparison, config analysis, or filename.
Confidence
A calibrated 0–1 score, on the component and on each individual occurrence.
Detector ID
The stable rule that fired, e.g. rules/openai/model-literal.

That lands as CycloneDX evidence.occurrences[] — the field other AIBOM tools leave empty. Every row is a claim you can walk back to a line of source.

Unknown ≠ supported

It says what it doesn’t know

A version it couldn’t resolve stays empty instead of guessing. A model outside the lifecycle catalog carries no claim, never a quiet “supported”.

Ranges ≠ versions

A declared range is not a release

>=1.0,<2 is recorded as a constraint, not a version — which is what stops the CVE overlay matching advisories against a release nobody confirmed is installed.

Reproducible

Byte-identical output

The same tree produces the same document at any worker count. Determinism is an invariant, enforced by tests, not a side effect.

What it finds

Across Python, JavaScript, TypeScript, Go, Java, Rust, C#, Kotlin and SQL.

Hosted models OpenAI, Anthropic, Gemini, Bedrock, Azure OpenAI, Cohere, Mistral, Groq — model IDs and SDK call sites.
Local weights GGUF, safetensors, ONNX, PyTorch, SavedModel, TFLite, HDF5, TensorRT — identified by magic bytes and bounded header parsing. Never loaded or run.
Frameworks LangChain, LlamaIndex, CrewAI, Agno, AutoGen, Semantic Kernel, CAMEL, MetaGPT, Letta, Crawl4AI, FastMCP, Transformers, and more.
Local inference & training vLLM, llama.cpp, GPT4All, Ollama, DeepSpeed, Unsloth.
Vector databases Chroma, Milvus, Qdrant, Pinecone, Weaviate, FAISS, Redis, pgvector — including SQL schemas and a server-side pgvector install.
Prompts & datasets Prompt files and templates, CSV/JSONL/Parquet signatures, load_dataset(), Hugging Face and Kaggle references.
Everything else Generation parameters bound to their call site, serving infrastructure, and RAG pipelines stitched into one component.

Dependencies are read from manifests, lockfiles, installed metadata, and even PyInstaller binaries — so a frozen app with no source on disk still produces an inventory.

143
detection rules
61
rule packs
35
detectors
9
languages

One scan, every format

Writers are pure projections of one graph — no re-derivation, no drift between them.

FormatFlagNotes
CycloneDX 1.6 / 1.7cyclonedxML-BOM with modelCard, evidence.occurrences[], vulnerabilities and compliance attestations.
SPDX 3.0.1spdxJSON-LD across the AI, Dataset, Software and Security profiles.
SARIF 2.1.0sarifOne result per occurrence — lands as GitHub Code Scanning alerts.
OpenVEX 0.2.0vexOver the CVE overlay. Only ever asserts affected.
Native JSON / YAMLjson · yamlThe two lossless formats. Round-trip the whole graph.
Table · Markdowntable · complianceHuman review in a terminal, and a Markdown compliance report.

Gate a build

# many formats, one pass
airom scan . -o cyclonedx=bom.json -o spdx=bom.spdx.json

# fail the build on what matters
airom scan . --exit-code 1 --fail-on "risk:high|cve:critical"

In GitHub Actions

- run: pip install airom
- run: airom scan . -o sarif=airom.sarif
- uses: github/codeql-action/upload-sarif@v3
  with: { sarif_file: airom.sarif }

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. --offline asserts it globally.
  • Signed releases. CGO_ENABLED=0, cosign-signed, shipping an SBOM and a self-scanned AIBOM.

Where it stands

v0.3.6 — early but real. The pipeline, detectors, writers and overlays are implemented and tested. Expect rough edges.

Known gaps, each also surfaced in the affected flag’s --help: caching is not implemented, live registry and daemon image pulls are not available (use airom image --input <archive>), and live-cluster scanning is not available (use airom k8s --manifests <dir>).

The full ledger — what’s complete, what’s deferred, and how AIROM compares to adjacent tools — is in project status.

Scan something

One command, one static binary. Point it at a repo and see what comes back.

$ pip install airom && airom scan .
Read the docs