airom

module
v0.1.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 22, 2026 License: Apache-2.0

README

AIROM

Open-source AI Bill of Materials (AIBOM) scanner.

AIROM is an open-source scanner that discovers AI assets — including models, prompts, datasets, embeddings, vector databases, and AI frameworks — and generates AI Bills of Materials (AIBOMs). It runs as a single static binary over a filesystem, source repository, container image, or Kubernetes cluster, and puts file:line evidence behind every entry.

CI Release Go Report Card Go Reference

v0.1.5. Early but real: the pipeline, detectors, rule packs, and every writer are implemented and tested, with the AI-native risk overlay and compliance framework mapping (see Risk detection and Compliance mapping). The terminal output is a boxed scan-summary panel and a component table with LOCATION, RISK, and FLAGS columns, and --wide expands every occurrence under each component. See Project status for the honest ledger of what ships today versus what is deferred.


What is AIROM?

Sooner or later, an auditor, a customer, or your own security team asks the question:

"Your AIBOM says this service uses gpt-4.1. Why? Where, exactly?"

Most AIBOM tools can't answer it. They are registry-centric — you name a model on Hugging Face, they render a model card — or they are proprietary and never look at your code at all. Nobody scans the repository you actually ship and shows their work.

AIROM is evidence-first. Every component in the output carries:

  • Occurrencesfile:line, matched snippet, and enclosing symbol for every sighting
  • Detection technique — source-code analysis, binary header parse, manifest analysis, hash comparison, …
  • A calibrated confidence score — with the arithmetic behind it, not a vibe

That evidence is emitted as CycloneDX 1.6 evidence.identity[] + evidence.occurrences[] — a spec-native home for "seen at file:line, by technique T, with confidence C" that AIBOM tools routinely leave empty — plus a SARIF projection so the same findings land as annotations in GitHub Code Scanning. One scan, one graph, every format a pure projection of it.

How it relates to SBOM tooling. An SBOM scanner inventories software packages to produce an SBOM; AIROM inventories AI-specific assets — models, datasets, prompts, vector stores, serving infrastructure — to produce an AIBOM. It is the AI-asset counterpart to software-dependency scanning, its own tool with its own problem space.

What AIROM detects

Category Coverage
Hosted model APIs OpenAI, Anthropic, Gemini, AWS Bedrock, Azure OpenAI, Cohere, Mistral, Groq, Ollama — model-ID literals and SDK call sites
Local model weights GGUF, safetensors, ONNX, Torch (pickle-zip), TensorFlow SavedModel, TensorRT, TFLite, HDF5 — magic bytes + header metadata (architecture, parameter count, quantization), never loaded or executed
Model directories & lineage Hugging Face model dirs (config.json + weights = one component), PEFT/LoRA adapters → derived-from base-model edges
Embedding models OpenAI, sentence-transformers, BGE/E5/MiniLM, Voyage, Cohere — hosted or local
Frameworks & SDKs LangChain, LlamaIndex, Haystack, DSPy, CrewAI, AutoGen, Semantic Kernel, Transformers, vLLM, MLflow, and the provider SDKs — from manifests and usage
Vector databases Chroma, Milvus, Qdrant, Pinecone, Weaviate, FAISS, pgvector, Redis, Elasticsearch, MongoDB Atlas
Prompts Prompt files (txt/md/yaml/jinja), PromptTemplate/ChatPromptTemplate/system_prompt patterns
Datasets CSV/JSONL/Parquet/Arrow signatures, load_dataset(), Kaggle and HF dataset references
Generation parameters temperature, top_p, top_k, max_tokens, seed, stop, reasoning effort, response format — bound to the model at the call site, with provenance
Serving infrastructure Ollama, vLLM, TGI, Ray Serve, SageMaker, Vertex AI, Azure ML — including Dockerfile/compose/k8s manifests
RAG pipelines Retriever + vector store + embedder + LLM stitched into a synthesized rag-pipeline composite with typed, evidenced edges

Scan targets: filesystem · git repository (local or URL) · container image (--input tarball or OCI layout today; remote/daemon pull is a follow-up) · Kubernetes workloads (offline --manifests today; live-cluster is a follow-up)

Languages: Python, JavaScript, TypeScript, Go, Java, Rust, C#, Kotlin

Output formats: native AIBOM JSON (versioned schema) · CycloneDX 1.6 ML-BOM (with vulnerabilities[] for risks and definitions/declarations for compliance) · SARIF 2.1.0 · YAML · a Markdown compliance report · table — any combination in one scan. SPDX 3.0.1 AI profile is a reserved v2 slot.

Risk detection

Beyond inventory, AIROM flags AI-native security risks — load-time code-execution and injection surfaces that a generic SBOM or secret scanner never looks for. Each risk attaches to the component it concerns, carries file:line evidence, and is treated as suspicion with evidence, never a verdict: a static scan is evadable by construction, so the absence of a risk is not a safety claim.

Risk Severity What it catches
pickle-import high A Torch checkpoint whose pickle resolves a code-execution callable (os.system, subprocess, builtins.eval, …)
keras-lambda high A Keras HDF5 config declaring a Lambda layer — marshalled Python that runs at load_model
gguf-template medium A GGUF chat_template carrying Jinja sandbox-escape gadgets (__globals__, os.popen, …)
savedmodel-pyfunc medium A TensorFlow SavedModel graph invoking a PyFunc-family Python callback
unsafe-load medium A torch.load(..., weights_only=False) call site — an explicit opt-out of safe deserialization

Risks project natively into CycloneDX vulnerabilities[] (non-CVE ids with a named source; no fabricated CVSS), SARIF security results carrying GitHub's security-severity — so a poisoned checkpoint becomes a Code Scanning alert on the PR that introduced it — a RISK column in the table view, and the CI gate:

airom scan . --exit-code 1 --fail-on "risk:high"          # fail on any high-severity risk
airom scan . --exit-code 1 --fail-on "risk:unsafe-load"   # or one specific risk

It stays deterministic and offline — no LLM, no vulnerability database. And it extends without Go: any rule pack can attach a catalog risk to a match via a risk: field. The full catalog and the model behind it are in docs/risks.md.

Compliance mapping

--compliance <framework> maps the AIBOM onto an AI-governance framework's controls and decides met / gap / manual for each — with the file:line evidence behind every verdict.

airom scan . --compliance nist-ai-rmf -o compliance=report.md -o cyclonedx=bom.json

It's a mapping, never a certification. Most of these frameworks are organizational process a static scan can't verify; those controls are marked manual and carry no score — AIROM never asserts conformance it can't back. An evidence_of "met" points at the concrete components that satisfy it. Frameworks today: nist-ai-rmf (NIST AI RMF 1.0) and owasp-agentic (OWASP Agentic AI — mostly manual, honestly, since agentic threats are runtime; its RCE threat maps to the risk overlay).

It projects into CycloneDX's native attestation modeldefinitions.standards[] (the framework + its requirements) and declarations (AIROM as a first-party assessor; a claim + graded conformance.score per control) — plus a Markdown report (-o compliance) and a CI gate:

airom scan . --compliance nist-ai-rmf --exit-code 1 --fail-on "compliance:gap"

That evidence-linked conformance is something a tool that drops evidence on export structurally cannot produce. Details and the honest-mapping contract are in docs/compliance.md.

Quick start

Install
# pip — no Go toolchain needed. Installs the `airom` command AND the Python SDK.
pip install airom        # or: pipx install airom  (isolated, always on PATH)

# From source (requires Go 1.25+). Resolves to the newest release tag.
go install github.com/airomhq/airom/cmd/airom@latest

Then airom --version should work from any directory.

airom: command not found? — it's on PATH, or it isn't.

The wheel installs airom into your environment's bin/, so pip puts it on PATH automatically inside an active virtualenv (pipx does so globally). go install writes to $(go env GOPATH)/bin, which Go does not add to PATH for you:

export PATH="$PATH:$(go env GOPATH)/bin"     # add to ~/.zshrc or ~/.bashrc

Check where it went with command -v airom, pip show -f airom, or go env GOPATH.

Prebuilt, cosign-signed binaries for all six targets are on the releases page, each with a checksum and an SBOM; a Homebrew tap is planned. AIROM releases as a single static binary (CGO_ENABLED=0) — no runtime, no dependencies.

Scan
# Auto-detect the target: directory, git URL, or image reference
airom scan .

# Explicit nouns — one subcommand per target type
airom fs ./my-service
airom repo https://github.com/org/rag-app
airom image --input img.tar          # docker save -o img.tar nginx:latest
airom k8s --manifests ./deploy       # offline: enumerate workload images

# Multiple outputs from one scan: table to the terminal,
# CycloneDX and SARIF to files
airom scan . -o table -o cyclonedx=bom.json -o sarif=scan.sarif

# Narrow the detector set; add your own rules
airom scan . --select "rules,+modelfile/gguf,-dataset/file" --rules extra.yaml

Exit codes: airom exits 0 when the scan succeeds — findings are not failures. Gating is opt-in CI policy:

airom scan . --exit-code 1 --fail-on "local-model-file&confidence>=0.9"

Example output

$ airom scan .

AI Bill of Materials — /tmp/my-rag-app

┌─ Scan Summary ────────────────┐
│ Target        /tmp/my-rag-app │
│ Components    12              │
│ Relationships 3               │
│ Files         5 scanned       │
│                               │
│ By Type                       │
│   ai-config          2        │
│   library            2        │
│   local-model-file   2        │
│   embedding-model    1        │
│   framework          1        │
│   hosted-llm         1        │
│   prompt             1        │
│   rag-pipeline       1        │
│   vector-db          1        │
│                               │
│ By Severity                   │
│   high               1        │
│   medium             0        │
│   low                0        │
└───────────────────────────────┘

┌──────────────────┬────────────────────────┬─────────┬─────────────┬───────┬──────┬───────────────┬────────────────────┬──────────┐
│ KIND             │ NAME                   │ VERSION │ PROVIDER    │ CONF  │ RISK │ FLAGS         │ LOCATION           │ EVIDENCE │
├──────────────────┼────────────────────────┼─────────┼─────────────┼───────┼──────┼───────────────┼────────────────────┼──────────┤
│ ai-config        │ max_tokens             │ -       │ -           │ 0.5   │ -    │ -             │ src/rag.py:17      │ 1 occ    │
│ ai-config        │ temperature            │ -       │ -           │ 0.5   │ -    │ -             │ src/rag.py:16      │ 1 occ    │
│ 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    │
│ library          │ sentence-transformers  │ 3.1.1   │ huggingface │ 0.95  │ -    │ -             │ requirements.txt:5 │ 1 occ    │
│ local-model-file │ poisoned.pt            │ -       │ local       │ 0.95  │ high │ pickle-import │ models/poisoned.pt │ 1 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    │
└──────────────────┴────────────────────────┴─────────┴─────────────┴───────┴──────┴───────────────┴────────────────────┴──────────┘

The poisoned.pt row shows the risk overlay inline: a high severity with the pickle-import flag. Risk-free scans omit the RISK/FLAGS columns. LOCATION is each component's primary file:line; --wide lists every occurrence.

And the answer to the auditor's question, in the CycloneDX BOM (abridged):

{
  "type": "machine-learning-model",
  "bom-ref": "airom:1f3a9b2c4d5e6f70",
  "group": "openai",
  "name": "gpt-4.1",
  "modelCard": { "modelParameters": { "task": "text-generation" } },
  "properties": [
    { "name": "airom:model.provider", "value": "openai" },
    { "name": "airom:model.id", "value": "gpt-4.1" },
    { "name": "airom:confidence", "value": "0.87" },
    { "name": "airom:param.temperature", "value": "0.2 @ src/rag.py:88" }
  ],
  "evidence": {
    "identity": [
      {
        "field": "name",
        "confidence": 0.87,
        "methods": [
          { "technique": "source-code-analysis", "confidence": 0.85,
            "value": "model=\"gpt-4.1\"" }
        ]
      }
    ],
    "occurrences": [
      { "location": "src/rag.py", "line": 88, "symbol": "answer_question",
        "additionalContext": "client.chat.completions.create(model=\"gpt-4.1\", temperature=0.2)" },
      { "location": "src/summarize.py", "line": 41, "symbol": "summarize" }
      // …10 more
    ]
  }
}

Note what's not there: no fabricated pkg:generic/openai/gpt-4.1 purl. Hosted API models aren't packages; AIROM identifies them via bom-ref and namespaced properties rather than polluting purl-keyed consumers like Dependency-Track. Local weight files, by contrast, get real purls (pkg:huggingface/..., pkg:generic?checksum=...) and SHA-256 hashes — their identity is their bytes, so the same weights at three paths are one component with three occurrences.

Confidence is never hand-waved: per-detector sightings are capped (twelve hits of one regex ≈ one hit, slightly reinforced — repetition can't launder into certainty), independent detection methods corroborate via noisy-OR, and everything clamps at 0.99. Only a content-hash match against known weights may assert 1.0.

How it works

source (fs / repo / image / k8s)
  → Phase 1 — streaming scan: one bounded pipeline; each file read at most once;
    a compiled selector index picks interested detectors; the rule engine runs
    Aho–Corasick keyword prefilters over lexed code/string regions before any regex
  → Phase 2 — project detectors: cross-file logic (HF model dirs, adapter lineage,
    config⇄model binding, RAG stitching) over an immutable phase-1 view
  → Assembler: canonical identity, keep-and-relate merge, confidence calculus,
    parameter binding — detectors emit claims, never components
  → Writers: pure functions from one graph to every output format.

The properties that make it production-grade are invariants, not aspirations: peak memory is a function of configuration, never input size; a corrupt file degrades to an honest Unknown record instead of killing the scan; identical inputs produce byte-identical output at any parallelism; a 40 GB GGUF inside a container image costs a 32 KB header parse and a hashing pass — zero memory growth, zero disk. Each of these gets a dedicated CI enforcement test as the test matrix lands (Phase 8).

The full design — domain model, detector framework, concurrency topology, identity and confidence calculus, caching, and the decision log with rejected alternatives — is in docs/ARCHITECTURE.md.

Extending AIROM

The detection surface that moves fast — model IDs churn weekly — lives in declarative YAML rule packs, not Go. Adding a provider is a rules PR, never a release, and the target is under one hour:

  1. airom dev new-rulepack fireworks scaffolds rules/models/fireworks.yaml plus fixture stubs.
  2. Write ~30 lines of YAML: keywords (mandatory — they gate an Aho–Corasick prefilter, so your regex only ever runs on files that could match), a pattern or two, a claim template. Add a positive and a negative fixture.
  3. airom rules lint && go test ./rules/... -update writes the golden output.
  4. Your PR is one YAML file, two fixtures, one golden. Zero Go, zero core changes. Review is "do the goldens look right."

Rules can even declare relationships and capture generation parameters at the call site — edges from YAML, no code. For detections that need a real parser (binary headers, cross-file assembly), the Go path is nearly as short: implement FileDetector against the stdlib-only pkg/airom/detect SDK and validate it with the public detectortest harness — the same one the built-in detectors use.

Project status

AIROM is at v0.1.5: feature-complete against the 10-phase plan, architecture through a multi-agent production review, with the risk overlay, compliance mapping, and a reworked terminal table added on top. Early software — expect rough edges, and see the deferred row below for what it deliberately does not do yet. Honest ledger:

Area Status
Architecture, domain model, decision log (docs/ARCHITECTURE.md) Complete — accepted v1 baseline
Repository scaffolding on the §4 layout (packages and their contracts, build files, docs) Complete — Phase 2
CLI (docs/cli.md): scan/fs/repo/image/k8s/clean/version, config layering (flags > env > file > defaults), exit-code contract, --fail-on grammar, pprof/trace bootstrap Complete — Phase 3, plus grouped/styled help and a live scan progress indicator that degrades to nothing off a terminal
Filesystem scanner: dir source (nested .gitignore/.airomignore stack, default skips, symlink safety), classification (language/binary/magic), read-once tee-hashed file context, phase-1 streaming pipeline (bounded channels, clamped I/O budget, panic isolation, deterministic output) Complete — Phase 4
Plugin framework: public SDK (pkg/airom domain graph with tri-state fields, pkg/airom/detect contracts + dispatch index, purl discipline, detectortest harness), dispatcher with per-detector isolation and accounting, explicit catalog + Syft-style --select, assembler (CanonicalKey identity, keep-and-relate merge, grouped noisy-OR confidence, refusal-first relations), rule-engine compiler (full rule-schema.md lint contract, three-layer merge, self-invalidating ruleset hash, Aho–Corasick prefilter, region lexers for all 8 languages), detectors-gen, airom detectors list/explain Complete — Phase 5. airom fs . --rules pack.yaml runs user rule packs end-to-end today
Detectors & rule packs: binary model-file parsers (GGUF, safetensors, ONNX, Torch, SavedModel, TFLite, HDF5, TensorRT — fuzzed) with an artifact-risk overlay (pickle imports, Keras Lambda, GGUF template gadgets, SavedModel PyFunc → CycloneDX vulnerabilities[]/SARIF), 8-ecosystem manifest detectors, Go AST detector, prompt/dataset/infra detectors, phase-2 project detectors (HF-dir assembly, adapter lineage, config binding, RAG synthesis), 49 embedded rule packs / 101 rules across 9 categories (incl. a security category and a rule-level risk: field), rules list/lint/test + dev scaffolding Complete — Phase 6. Scans a real AI project into a rich AIBOM (models, embeddings, vector DBs, frameworks, weights, prompts, infra, RAG pipelines)
Sources: repo (exec-git shallow clone + local worktrees), image (docker-save/OCI archive + OCI layout — live registry/daemon pull is a follow-up), k8s (offline --manifests image enumeration — live cluster is a follow-up) Complete — Phase 6 (with the noted follow-ups)
Writers: native JSON (versioned, lossless superset — round-trip tested), CycloneDX 1.6/1.7 ML-BOM (modelCard + evidence.occurrences[] + vulnerabilities[] for risks + definitions/declarations for compliance, validated against the official schemas), SARIF 2.1.0 (one rule per detector/risk, one result per occurrence, line-free fingerprints), YAML, a Markdown compliance report, table; multi-output -o fmt=path Complete — Phase 7. airom scan . -o cyclonedx=bom.json -o sarif=scan.sarif emits both from one pass
Compliance mapping (--compliance): AIBOM → governance-framework controls (met/gap/manual, no fabricated scores), projected as CycloneDX attestations + a Markdown report, gateable via --fail-on compliance:gap. Frameworks: NIST AI RMF 1.0, OWASP Agentic AI (docs/compliance.md) Complete — evidence-linked, deterministic, offline
Test suite: golden end-to-end fixture repos through the whole pipeline into all five formats, official CycloneDX/SARIF schema conformance, docs/mapping.md round-trip enforcement, full-scan determinism (--parallel 1 vs 16), chaos degradation, and a P2 RSS-ceiling regression harness — everything under -race, ~74% coverage Complete — Phase 8
Release automation: CI (lint/vet/gofmt, -race tests on Linux+macOS, CGO_ENABLED=0 cross-compile matrix for all six targets, generated-code drift check, fuzz smoke, CodeQL), goreleaser (static matrix builds, checksums, keyless cosign signing, per-release SBOM + self-scanned AIBOM), Dependabot, issue/PR templates, SECURITY.md/CODE_OF_CONDUCT.md/CONTRIBUTING.md Complete — Phase 9
Production hardening: whole-tree adversarial review (10 dimensions, per-finding verification) that found and fixed 17 verified defects — an OCI-layout path-traversal escape, a static-pickle scan evasion via memo/GET, the unwired --fail-on CI gate, a P7 stack-trace leak, YAML int64 corruption, non-canonical purls, and detector/rule-prefilter gaps — each with a regression test. Confirmed the empty CycloneDX dependencies[] (no substantiated depends-on edges) and the deferred live registry/daemon/cluster modes (fail cleanly) are deliberate, not defects Complete — Phase 10
SPDX 3.0.1 AI profile, attestation verification, per-layer attribution, OCI rule registry, live-cluster/registry source modes, root→dependency edge synthesis Deferred to v2 by design (reserved slots — see ARCHITECTURE §16)

Known gaps, each surfaced in the affected flag's own --help rather than only here: caching is not implemented (every scan is cold, --no-cache is a no-op), live registry/daemon image pulls are not available (use airom image --input <archive>), and live-cluster scanning is not available (use airom k8s --manifests <dir>).

Comparison

No FUD, just positioning — the tools below solve different problems:

AIROM Registry-centric AIBOM generators Proprietary AI security scanners
Input Your repo, image, or cluster A registry entry you name (e.g. an HF repo) Varies; often model artifacts or SaaS-connected repos
Answers "why is this in my AIBOM?" Yes — file:line occurrences, technique, confidence in the BOM No — output describes the model, not your usage of it Typically findings without BOM-native evidence
CycloneDX evidence.occurrences[] Emitted Not emitted Not emitted
Load-time risk detection Built in — pickle / Lambda / template / PyFunc / unsafe-load, as CycloneDX vulnerabilities[] + SARIF, offline No Varies — some scan model artifacts, typically SaaS or agent-based
Compliance mapping Evidence-linked — NIST AI RMF / OWASP Agentic as CycloneDX attestations, honest about what a scan can't verify No Sometimes, but without BOM-native evidence
Coverage Hosted APIs and local weights and frameworks, vector DBs, prompts, datasets, params, infra, RAG graphs The named model Usually model files and/or a curated subset
Distribution Single static Go binary, offline-capable Python package Agent or SaaS
License Apache 2.0 Varies (often open source) Proprietary

If you already know exactly which registry model you use and want its card, a registry-centric generator is the right tool. AIROM is for when the ground truth is your codebase and you have to prove it.

Security

AIROM is a security tool whose parsers eat untrusted bytes, and is hardened accordingly. The posture below is binding design contract (ARCHITECTURE §13); the fuzzing and release machinery that enforce it land with the test and release phases (see Project status):

  • No model execution, ever. Weight files are identified by magic bytes and bounded header parsing only — nothing is loaded, deserialized into objects, or run.
  • Static artifact-risk scanning. Model files and load-time code are walked for execution/injection surfaces — pickle imports, Keras Lambda layers, GGUF template gadgets, SavedModel Python callbacks, unsafe torch.load — without ever executing them. Findings surface as an evidence-linked risk overlay (CycloneDX vulnerabilities[], SARIF, --fail-on risk); see Risk detection and docs/risks.md.
  • Fuzzed parsers. Every binary header parser is fuzzed in CI and must return errors — never panic, never allocate unbounded.
  • No surprise network access. Filesystem, local-repo, and image --input scans touch no network; --offline asserts it globally.
  • Supply chain. Releases are CGO_ENABLED=0, reproducibly built, cosign-signed, and ship with an SBOM — and, dogfooded, an AIBOM.

Report vulnerabilities privately via a GitHub security advisory on the repository, not a public issue — see SECURITY.md.

Contributing

Start with CONTRIBUTING.md and docs/plugin-guide.md. The fastest way to make AIROM better is a rule pack: one YAML file, two fixtures, one golden — most providers land in under an hour.

License

Licensed under the Apache License 2.0. © AIROM contributors

Directories

Path Synopsis
cmd
airom command
Command airom is the AIROM CLI entrypoint.
Command airom is the AIROM CLI entrypoint.
internal
app
Package app is the composition root — the ONLY wiring site in the codebase (ARCHITECTURE.md §12, decision D4).
Package app is the composition root — the ONLY wiring site in the codebase (ARCHITECTURE.md §12, decision D4).
assemble
Package assemble is the heart of the pipeline (ARCHITECTURE.md §9): the single-threaded, deterministic stage that turns detector claims into the canonical component graph.
Package assemble is the heart of the pipeline (ARCHITECTURE.md §9): the single-threaded, deterministic stage that turns detector claims into the canonical component graph.
cache
Package cache implements the bbolt-backed scan cache (ARCHITECTURE.md §10, decision D10).
Package cache implements the bbolt-backed scan cache (ARCHITECTURE.md §10, decision D10).
classify
Package classify implements file classification (ARCHITECTURE.md §3, §4): language identification from paths, binary sniffing over the shared header sample, and the magic-byte registry that routes model files to their header parsers.
Package classify implements file classification (ARCHITECTURE.md §3, §4): language identification from paths, binary sniffing over the shared header sample, and the magic-byte registry that routes model files to their header parsers.
cli
Package cli implements the airom command tree, configuration layering, and exit-code policy (ARCHITECTURE.md §12, docs/cli.md).
Package cli implements the airom command tree, configuration layering, and exit-code policy (ARCHITECTURE.md §12, docs/cli.md).
compliance
Package compliance maps a named AI-governance framework's controls onto an assembled AIROM inventory.
Package compliance maps a named AI-governance framework's controls onto an assembled AIROM inventory.
conformance
Package conformance is AIROM's output-format conformance suite: a permanent, CI-enforced check that every writer's bytes satisfy the external contract the format claims to speak (docs/mapping.md).
Package conformance is AIROM's output-format conformance suite: a permanent, CI-enforced check that every writer's bytes satisfy the external contract the format claims to speak (docs/mapping.md).
detectors/all
Package all holds the GENERATED registration list of built-in detectors (ARCHITECTURE.md §6.2): no hand-edited central file for every detector PR to conflict on.
Package all holds the GENERATED registration list of built-in detectors (ARCHITECTURE.md §6.2): no hand-edited central file for every detector PR to conflict on.
detectors/dataset
Package dataset detects dataset files by format signature (ARCHITECTURE.md §4, §17): CSV and JSONL by structural sniffing of the shared header sample, Parquet and Arrow by magic bytes — emitting KindDataset claims that phase-2 stitching can attach to models via TRAINED_ON edges (the SPDX trainedOn mapping).
Package dataset detects dataset files by format signature (ARCHITECTURE.md §4, §17): CSV and JSONL by structural sniffing of the shared header sample, Parquet and Arrow by magic bytes — emitting KindDataset claims that phase-2 stitching can attach to models via TRAINED_ON edges (the SPDX trainedOn mapping).
detectors/gosrc
Package gosrc detects AI usage in Go source with the stdlib go/parser (ARCHITECTURE.md §6.4, decision D1): exact AST analysis of import paths, SDK call sites, and model-name literals — Go is the one language where a real parser is free, so it gets one instead of the region-lexer + regex path used elsewhere.
Package gosrc detects AI usage in Go source with the stdlib go/parser (ARCHITECTURE.md §6.4, decision D1): exact AST analysis of import paths, SDK call sites, and model-name literals — Go is the one language where a real parser is free, so it gets one instead of the region-lexer + regex path used elsewhere.
detectors/infra
Package infra detects AI serving-infrastructure signals in deployment artifacts (ARCHITECTURE.md §4, §17): Dockerfiles (AI base images such as ollama or vllm, model-pulling build steps), docker-compose services, and Kubernetes manifests — emitting KindInfra and KindService claims eligible for SERVED_BY and CONFIGURES edges, using MethodConfig evidence.
Package infra detects AI serving-infrastructure signals in deployment artifacts (ARCHITECTURE.md §4, §17): Dockerfiles (AI base images such as ollama or vllm, model-pulling build steps), docker-compose services, and Kubernetes manifests — emitting KindInfra and KindService claims eligible for SERVED_BY and CONFIGURES edges, using MethodConfig evidence.
detectors/manifest
Package manifest detects AI frameworks and SDKs declared in package manifests and lockfiles (ARCHITECTURE.md §4, §17): requirements.txt, pyproject.toml, package.json, go.mod, pom.xml, Gradle lockfiles, Cargo.toml, and csproj, emitting framework and library claims with declared versions.
Package manifest detects AI frameworks and SDKs declared in package manifests and lockfiles (ARCHITECTURE.md §4, §17): requirements.txt, pyproject.toml, package.json, go.mod, pom.xml, Gradle lockfiles, Cargo.toml, and csproj, emitting framework and library claims with declared versions.
detectors/modelfile
Package modelfile detects local model weight files by magic bytes and header-only parsing — core IP (ARCHITECTURE.md §4, §17): GGUF, safetensors, ONNX, torch zips (with static pickle opcode walking), TensorFlow SavedModel, TensorRT engines, TFLite, and HDF5.
Package modelfile detects local model weight files by magic bytes and header-only parsing — core IP (ARCHITECTURE.md §4, §17): GGUF, safetensors, ONNX, torch zips (with static pickle opcode walking), TensorFlow SavedModel, TensorRT engines, TFLite, and HDF5.
detectors/modelfilex
Package modelfilex implements binary "local model file" detectors for model serialization formats whose recognition needs more than a magic-byte gate: PyTorch archives (with a static, non-executing pickle opcode walk that flags dangerous imports), TensorFlow SavedModel protobufs, TFLite flatbuffers, Keras/HDF5 weight stores, and opaque TensorRT engines.
Package modelfilex implements binary "local model file" detectors for model serialization formats whose recognition needs more than a magic-byte gate: PyTorch archives (with a static, non-executing pickle opcode walk that flags dangerous imports), TensorFlow SavedModel protobufs, TFLite flatbuffers, Keras/HDF5 weight stores, and opaque TensorRT engines.
detectors/project
Package project holds the built-in phase-2 ProjectDetectors (ARCHITECTURE.md §3, §17) — cross-file logic the streaming phase cannot express: hfdir assembles a HuggingFace model directory (config.json + weights) into ONE component; adapterlink turns adapter_config.json into DERIVED_FROM base-model lineage; configbind attaches separated generation configs to the model they name via CONFIGURES edges under the refusal-first ambiguity policy (§9.5) — never a guessed edge; raglink stitches retriever, store, and embedder findings into a rag-pipeline composite with CONTAINS/QUERIES/EMBEDS_WITH edges; lockjoin joins manifests with their lockfiles.
Package project holds the built-in phase-2 ProjectDetectors (ARCHITECTURE.md §3, §17) — cross-file logic the streaming phase cannot express: hfdir assembles a HuggingFace model directory (config.json + weights) into ONE component; adapterlink turns adapter_config.json into DERIVED_FROM base-model lineage; configbind attaches separated generation configs to the model they name via CONFIGURES edges under the refusal-first ambiguity policy (§9.5) — never a guessed edge; raglink stitches retriever, store, and embedder findings into a rag-pipeline composite with CONTAINS/QUERIES/EMBEDS_WITH edges; lockjoin joins manifests with their lockfiles.
detectors/prompt
Package prompt detects prompt assets stored as standalone files (ARCHITECTURE.md §4, §17): .txt/.md/.yaml/.jinja content judged by template heuristics — placeholder syntax, role markers, instruction shape — plus prompt-suggestive path signals, emitting KindPrompt claims that can receive PROMPTED_BY edges.
Package prompt detects prompt assets stored as standalone files (ARCHITECTURE.md §4, §17): .txt/.md/.yaml/.jinja content judged by template heuristics — placeholder syntax, role markers, instruction shape — plus prompt-suggestive path signals, emitting KindPrompt claims that can receive PROMPTED_BY edges.
dispatch
Package dispatch routes classified files to interested detectors through the compiled selector index (ARCHITECTURE.md §6.1) and adapts the internal read-once file context to the public SDK's detect.File.
Package dispatch routes classified files to interested detectors through the compiled selector index (ARCHITECTURE.md §6.1) and adapts the internal read-once file context to the public SDK's detect.File.
engine
Package engine drives the two-phase scan pipeline (ARCHITECTURE.md §3, §8): phase 1 streams files from exactly one walker/producer through a bounded task channel into a worker pool where all matched detectors run SEQUENTIALLY on one shared buffer, with exactly one collector goroutine owning all mutable aggregation state — no locks.
Package engine drives the two-phase scan pipeline (ARCHITECTURE.md §3, §8): phase 1 streams files from exactly one walker/producer through a bounded task channel into a worker pool where all matched detectors run SEQUENTIALLY on one shared buffer, with exactly one collector goroutine owning all mutable aggregation state — no locks.
filectx
Package filectx implements the read-once file access contract (ARCHITECTURE.md §8, invariant P1): each file's bytes are read from the source at most once, and every interested detector shares that one buffer — detectors for a file run sequentially in one worker, so no buffer synchronization exists or is needed.
Package filectx implements the read-once file access contract (ARCHITECTURE.md §8, invariant P1): each file's bytes are read from the source at most once, and every interested detector shares that one buffer — detectors for a file run sequentially in one worker, so no buffer synchronization exists or is needed.
metrics
Package metrics makes profiling a product feature (ARCHITECTURE.md §14): ScanStats accumulates files walked and skipped, bytes read versus bytes in tree, cache hit rates, per-detector nanoseconds and invocation counts, and the selection explanation of which --select expression enabled which detector (§6.2) — embedded into the Inventory under --stats, so "what did the scanner skip" is always answerable and detector #217 is triaged with data, not guesses.
Package metrics makes profiling a product feature (ARCHITECTURE.md §14): ScanStats accumulates files walked and skipped, bytes read versus bytes in tree, cache hit rates, per-detector nanoseconds and invocation counts, and the selection explanation of which --select expression enabled which detector (§6.2) — embedded into the Inventory under --stats, so "what did the scanner skip" is always answerable and detector #217 is triaged with data, not guesses.
perf
Package perf is AIROM's performance-regression harness (ARCHITECTURE.md invariant P2: peak memory is a function of CONFIGURATION, never of input size).
Package perf is AIROM's performance-regression harness (ARCHITECTURE.md invariant P2: peak memory is a function of CONFIGURATION, never of input size).
ruleengine
Package ruleengine implements the declarative rule-pack compiler and the generic rule detector (ARCHITECTURE.md §6.3, docs/rule-schema.md — this package implements exactly that contract).
Package ruleengine implements the declarative rule-pack compiler and the generic rule detector (ARCHITECTURE.md §6.3, docs/rule-schema.md — this package implements exactly that contract).
ruleengine/lexer
Package lexer splits source text into code / comment / string regions for the rule engine (ARCHITECTURE.md §6.4, decision D1; docs/rule-schema.md "regions").
Package lexer splits source text into code / comment / string regions for the rule engine (ARCHITECTURE.md §6.4, decision D1; docs/rule-schema.md "regions").
ruleengine/ruletest
Package ruletest runs rule packs against annotated fixtures — the shared engine behind `airom rules test`/`lint` and the embedded-pack CI test (docs/rule-schema.md "Fixtures and the lint contract").
Package ruletest runs rule packs against annotated fixtures — the shared engine behind `airom rules test`/`lint` and the embedded-pack CI test (docs/rule-schema.md "Fixtures and the lint contract").
source
Package source defines the Source abstraction over scan targets (ARCHITECTURE.md §7): a Source couples a Walker (push-style, ignore-aware enumeration feeding phase 1), a Resolver (pull-style access for phase-2 project detectors), content identity (image digest, git HEAD, dir realpath), layer IDs for blob-cache granularity, and SourceInfo provenance.
Package source defines the Source abstraction over scan targets (ARCHITECTURE.md §7): a Source couples a Walker (push-style, ignore-aware enumeration feeding phase 1), a Resolver (pull-style access for phase-2 project detectors), content identity (image digest, git HEAD, dir realpath), layer IDs for blob-cache granularity, and SourceInfo provenance.
source/dirsource
Package dirsource implements the filesystem source (ARCHITECTURE.md §7): streaming enumeration with a nested per-directory .gitignore/.airomignore stack, non-overridable default skips, user --ignore globs, and an ignore-honoring resolver for the phase-2 pull API.
Package dirsource implements the filesystem source (ARCHITECTURE.md §7): streaming enumeration with a nested per-directory .gitignore/.airomignore stack, non-overridable default skips, user --ignore globs, and an ignore-honoring resolver for the phase-2 pull API.
source/gitsource
Package gitsource implements the remote-repository Source (ARCHITECTURE.md §7): git clone --depth=1 --single-branch --no-tags via an exec-git fast path when a git binary is available, with a go-git v6 fallback (decision D14: go-git's shallow-clone inefficiency is documented; established scanners shell out too).
Package gitsource implements the remote-repository Source (ARCHITECTURE.md §7): git clone --depth=1 --single-branch --no-tags via an exec-git fast path when a git binary is available, with a go-git v6 fallback (decision D14: go-git's shallow-clone inefficiency is documented; established scanners shell out too).
source/imagesource
Package imagesource implements the container-image Source (ARCHITECTURE.md §7, decision D11): go-containerregistry resolves a v1.Image through the remote → daemon → tarball → OCI-layout fallback chain, and the squashed tar from mutate.Extract is streamed exactly once.
Package imagesource implements the container-image Source (ARCHITECTURE.md §7, decision D11): go-containerregistry resolves a v1.Image through the remote → daemon → tarball → OCI-layout fallback chain, and the squashed tar from mutate.Extract is streamed exactly once.
source/k8ssource
Package k8ssource implements the Kubernetes Source (ARCHITECTURE.md §7).
Package k8ssource implements the Kubernetes Source (ARCHITECTURE.md §7).
tui
Package tui holds AIROM's terminal presentation primitives: TTY detection, ANSI styling, and the scan progress indicator.
Package tui holds AIROM's terminal presentation primitives: TTY detection, ANSI styling, and the scan progress indicator.
writer
Package writer defines the output stage (ARCHITECTURE.md §11): a Writer is a pure function from *airom.Inventory to bytes (invariant P5) that never invents, drops, or re-derives data — every format is a projection of the same assembled graph.
Package writer defines the output stage (ARCHITECTURE.md §11): a Writer is a pure function from *airom.Inventory to bytes (invariant P5) that never invents, drops, or re-derives data — every format is a projection of the same assembled graph.
writer/cdx
Package cdx projects the inventory to CycloneDX ML-BOM via CycloneDX/cyclonedx-go (ARCHITECTURE.md §11, decision D16) — 1.6 by default, 1.7 via --cdx-version (the modelCard shape is identical in both).
Package cdx projects the inventory to CycloneDX ML-BOM via CycloneDX/cyclonedx-go (ARCHITECTURE.md §11, decision D16) — 1.6 by default, 1.7 via --cdx-version (the modelCard shape is identical in both).
writer/compliancew
Package compliancew writes the human-readable compliance report (docs/compliance.md): each framework's controls as met / gap / manual, with the component evidence behind every verdict and a per-framework summary.
Package compliancew writes the human-readable compliance report (docs/compliance.md): each framework's controls as met / gap / manual, with the component evidence behind every verdict and a per-framework summary.
writer/nativejson
Package nativejson emits AIROM's native JSON format (ARCHITECTURE.md §11): the lossless, round-trip reference serialization of the Inventory graph, versioned from release one (schemaVersion "1") with its JSON Schema published per release under schemas/ and enforced by conformance and fuzz round-trip tests in CI (§14).
Package nativejson emits AIROM's native JSON format (ARCHITECTURE.md §11): the lossless, round-trip reference serialization of the Inventory graph, versioned from release one (schemaVersion "1") with its JSON Schema published per release under schemas/ and enforced by conformance and fuzz round-trip tests in CI (§14).
writer/sarifw
Package sarifw projects the inventory to SARIF 2.1.0 for GitHub Code Scanning (ARCHITECTURE.md §11, docs/mapping.md §3/§7).
Package sarifw projects the inventory to SARIF 2.1.0 for GitHub Code Scanning (ARCHITECTURE.md §11, docs/mapping.md §3/§7).
writer/tablew
Package tablew renders the human-facing terminal summary (ARCHITECTURE.md §11): a boxed scan-summary panel followed by a box-drawn component table with columns KIND | NAME | VERSION | PROVIDER | CONF | LOCATION (the primary path:line sighting) | EVIDENCE (rendered "n occ"), plus RISK | FLAGS when a scan surfaces an artifact risk.
Package tablew renders the human-facing terminal summary (ARCHITECTURE.md §11): a boxed scan-summary panel followed by a box-drawn component table with columns KIND | NAME | VERSION | PROVIDER | CONF | LOCATION (the primary path:line sighting) | EVIDENCE (rendered "n occ"), plus RISK | FLAGS when a scan surfaces an artifact risk.
writer/writertest
Package writertest builds a representative Inventory shared by the writer tests and the mapping round-trip test — one fixture exercising every kind, tri-state, evidence shape, relationship type, and honesty record, so a single golden per format proves the whole projection.
Package writertest builds a representative Inventory shared by the writer tests and the mapping round-trip test — one fixture exercising every kind, tri-state, evidence shape, relationship type, and honesty record, so a single golden per format proves the whole projection.
writer/yamlw
Package yamlw renders the native inventory model as YAML through yaml.v3 with stable key order (ARCHITECTURE.md §11) — the same lossless content as the native JSON writer, in a form suited to human review.
Package yamlw renders the native inventory model as YAML through yaml.v3 with stable key order (ARCHITECTURE.md §11) — the same lossless content as the native JSON writer, in a form suited to human review.
xio
Package xio holds the bounded-I/O primitives behind the bounded-everything invariant (ARCHITECTURE.md §8, P2): sync.Pool buffer pools per size class (findings copy out ≤200-byte snippets and never retain buffers), the spool that grows from memory to a temp file under hard caps (≤4 MiB memory, ≤64 MiB tmpfile — §7), and the byte-weighted I/O semaphore (default budget 256 MiB, a separate knob from CPU parallelism) acquired at min(size, budget) around any read over 1 MiB.
Package xio holds the bounded-I/O primitives behind the bounded-everything invariant (ARCHITECTURE.md §8, P2): sync.Pool buffer pools per size class (findings copy out ≤200-byte snippets and never retain buffers), the spool that grows from memory to a temp file under hard caps (≤4 MiB memory, ≤64 MiB tmpfile — §7), and the byte-weighted I/O semaphore (default budget 256 MiB, a separate knob from CPU parallelism) acquired at min(size, budget) around any read over 1 MiB.
pkg
airom
Package airom is the canonical AIROM domain model (ARCHITECTURE.md §5): the component graph every writer projects and every detector's claims assemble into.
Package airom is the canonical AIROM domain model (ARCHITECTURE.md §5): the component graph every writer projects and every detector's claims assemble into.
airom/detect
Package detect is the public detector SDK (ARCHITECTURE.md §6.1): the contracts a detector implements, the read-once File it receives, the Finding claims it emits, and the selector index that routes files to detectors.
Package detect is the public detector SDK (ARCHITECTURE.md §6.1): the contracts a detector implements, the read-once File it receives, the Finding claims it emits, and the selector index that routes files to detectors.
airom/detectortest
Package detectortest is the public contract-test harness for AIROM detectors (ARCHITECTURE.md §14, plugin-guide.md B.4): built-in and third-party detectors prove themselves with the identical harness.
Package detectortest is the public contract-test harness for AIROM detectors (ARCHITECTURE.md §14, plugin-guide.md B.4): built-in and third-party detectors prove themselves with the identical harness.
airom/purl
Package purl builds package URLs under AIROM's purl discipline (ARCHITECTURE.md §9.4, decision D9): spec purl types only.
Package purl builds package URLs under AIROM's purl discipline (ARCHITECTURE.md §9.4, decision D9): spec purl types only.
Package rules embeds the built-in AIROM rule packs (ARCHITECTURE.md §6.3): the offline-by-construction default detection vocabulary, compiled into the binary and versioned with each release.
Package rules embeds the built-in AIROM rule packs (ARCHITECTURE.md §6.3): the offline-by-construction default detection vocabulary, compiled into the binary and versioned with each release.
Package schemas embeds AIROM's published JSON Schemas (docs/mapping.md): the native AIBOM format is a versioned API, and its schema ships with the binary and the repo.
Package schemas embeds AIROM's published JSON Schemas (docs/mapping.md): the native AIBOM format is a versioned API, and its schema ships with the binary and the repo.
tools
detectors-gen command
Command detectors-gen regenerates internal/detectors/all/all.go: the mechanical, conflict-free registration list of built-in detectors (ARCHITECTURE.md §6.2, plugin-guide.md B.5).
Command detectors-gen regenerates internal/detectors/all/all.go: the mechanical, conflict-free registration list of built-in detectors (ARCHITECTURE.md §6.2, plugin-guide.md B.5).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL