See what AI is in a codebase and what it can reach: SDKs, models, MCP servers and agent tools.
Two questions get hard to answer once a repo has agents in it: what AI is in here, and what can it touch?
aibom-scanner reads a codebase and writes an AI Bill of Materials (AIBOM). It lists every AI SDK and model the code
calls, every MCP server it wires up, and every tool an agent can call. Then it shows where those add up to a risk and
which NIST, ISO, EU AI Act and OWASP items each finding points at.
It is a static scan. It makes no network calls, uses no language model, and has zero dependencies. It stores no values from MCP configs (key names only) and masks key-shaped strings in the code lines it quotes.
Quick Start
pip install aibom-scanner
aibom-scanner scan --path /path/to/your/repo
Here is part of the output for a small support agent: one Python file that gives an agent web search, Gmail and a
shell, plus an .mcp.json with three servers. Long lines are cut.
Risk Findings (10)
...
[HIGH ] Agentic AI framework without human oversight controls
[HIGH ] Codebase combines untrusted input, sensitive data access and an action capability
[MEDIUM ] MCP server launched without a pinned version
[MEDIUM ] Agent tool can execute code
MCP Servers (3)
filesystem stdio npx pinned .mcp.json:2
fetch stdio uvx unpinned .mcp.json:3
github stdio docker unpinned .mcp.json:4
Tool Capabilities (6 classified tools)
code_execution 1 ShellTool
external_side_effect 3 GmailToolkit, ShellTool, @modelcontextprotocol/server-filesystem
model_call 1 ChatOpenAI
sensitive_data_access 2 GmailToolkit, @modelcontextprotocol/server-filesystem
untrusted_content_in 3 TavilySearchResults, GmailToolkit, mcp-server-fetch
The "Codebase combines" finding is the one I care about most. An agent that reads content from strangers, can reach private data and can act on the outside world is the setup that makes prompt injection dangerous. The JSON output names the tools behind each leg, so you can see which one to take away.
New in 1.3
- MCP server inventory. Every MCP server in the repo, one row each: how it is launched, its transport, whether the version is pinned, and the file and line. Read from MCP config files in any repo and from Python code.
- Agent tool capabilities. About 500 LangChain and CrewAI tools and 16 common MCP servers are classed by what they can do: read untrusted content, reach sensitive data, act on the outside world, run code.
- A finding for the dangerous combination. HIGH when one module holds all three legs, MEDIUM when they are spread across files or only listed in a config file.
- OWASP mappings. Findings link to the OWASP Top 10 for LLM Applications (2025) and the OWASP Top 10 for Agentic Applications (2026). The nine items a static scan cannot see are reported as GAP, not hidden.
- Hardcoded keys stay out of the report. 1.2.0 wrote the full value of a hardcoded key into the JSON output. 1.3.0 does not, and it masks key-shaped strings in quoted code lines. A 1.2.0 JSON report that found a hardcoded key holds that key. One limit: a key passed as a positional argument or inside a URL can still show in a snippet.
Full detail is in the changelog.
What It Finds
aibom-scanner detects AI SDKs in your codebase and generates an AI Bill of Materials (AIBOM) with compliance risk findings mapped to three compliance frameworks and two OWASP lists.
| 70 detection patterns | OpenAI, Anthropic, Google AI, AWS Bedrock, Cohere, Mistral, Groq, HuggingFace, and 21 more |
| Languages | Python, JS/TS, Go, Java, Rust, Ruby, Swift, C#/.NET — imports, API calls, and dependency manifests |
| 10 Chinese AI providers | 3 BIS Entity-Listed (Zhipu, iFlytek, SenseTime = CRITICAL), 7 data sovereignty flagged |
| Agentic AI detection | CrewAI, AutoGen, LangGraph, Semantic Kernel, MCP |
| MCP servers | Listed one by one from config files and Python code: transport, launch command, pinned or not |
| Agent tool capabilities | About 500 LangChain and CrewAI tools and 16 MCP servers, in five capability classes |
| 34 risk rules | 8 categories with evidence-qualified severity adjustment |
| 49 compliance controls | NIST AI RMF (23), ISO 42001 (15), EU AI Act (11) |
| 20 OWASP items | OWASP LLM Top 10 (2025) and OWASP Agentic Top 10 (2026), reported as MAPPED, PARTIAL or GAP; 9 have no static signal and always read GAP (see below) |
| Secrets detection | Hardcoded API keys, Vault, AWS Secrets Manager, dotenv |
| Dev tool detection | Cursor, GitHub Copilot, Claude Code, Aider, TabNine |
| Coverage accounting | Every scan reports what it read — and what it could not |
| Zero dependencies | Pure Python stdlib. Nothing to install but Python. |
MCP server inventory
The JSON output lists each MCP server in mcp_servers: name, transport (stdio, sse, http, hosted), command, args,
URL host, env and header key names, source file and line, and whether an npx, uvx, pipx run or docker run
command is version-pinned. Servers come from mcp.json, .mcp.json, mcp_config.json and claude_desktop_config.json
files and from Python code. Values are never stored: env and header entries are key names only, URLs are reduced to
scheme and host, and args is an allowlist: flag names, the package or image of an npx, uvx,
pipx run or docker run command, and --flag=<redacted>. Every other argument, including paths and flag
values, is shown as <arg>. Servers defined in C#, TypeScript or Go
source are not listed per server; summary.mcp_servers_note says so.
Tool capability classes
Tools an agent can call are classed as untrusted_content_in, sensitive_data_access, external_side_effect,
code_execution or model_call, in tool_capabilities and summary.capability_classes. Python tools are matched
by import against a table of about 500 LangChain and CrewAI tools. MCP servers are classed only when their package
(version stripped) is in a short table; others get no class and are never guessed from their name. A codebase that holds
untrusted input, sensitive data access and an action capability (external side effect or code execution) gets the HIGH
finding "Codebase combines untrusted input, sensitive data access and an action capability", with the tools as evidence.
It is HIGH when one Python module holds the three legs in at least two distinct tools (at least one found by import),
because those tools are available to the same module. Servers listed only in an MCP config file give MEDIUM: a config
file shows availability, not use. It is also MEDIUM when the legs are spread across files, because they may
belong to different agents. A short list of web search, scrape and browser
SDKs (for example tavily, firecrawl, playwright) also counts as untrusted_content_in, matched by import.
Tools that are not in the tables are not classified.
OWASP mappings
Findings link to the OWASP Top 10 for LLM Applications (2025, OWASP-LLM01..10) and the OWASP Top 10 for Agentic
Applications (2026, OWASP-ASI01..10). Eleven items are reachable by a finding today (LLM01, 02, 03, 05, 06 and
ASI01, 02, 03, 04, 05, 09). Nine have no static signal and are reported as GAP, never hidden: LLM04 Data and Model
Poisoning, LLM07 System Prompt Leakage, LLM08 Vector and Embedding Weaknesses, LLM09 Misinformation, LLM10 Unbounded
Consumption, ASI06 Memory and Context Poisoning, ASI07 Insecure Inter-Agent Communication, ASI08 Cascading Failures
and ASI10 Rogue Agents. A reachable item is PARTIAL when a finding points at it: the scanner reports a risk signal,
not proof that a control is in place. JSON shows all 20; SARIF shows the linked ids as rule tags; the table shows
the first three references per finding.
Two findings added with the mappings: "MCP server launched without a pinned version" and "Agent tool can execute code".
Coverage: what the scan actually read
An AI Bill of Materials that silently omits what it could not parse is not incomplete, it is wrong. Every scan reports its own denominator:
Scanned 86 of 173 source files (49.7%) — 86 test/fixture files excluded, 98.9% of source attempted
Two ratios, because either one alone misleads:
| Field | Meaning |
|---|---|
coverage_pct |
files_scanned / source_files_seen — the honest headline. Every source file in the tree is in the denominator. |
readable_coverage_pct |
files_scanned / (source_files_seen - skipped_by_path) — isolates scanner capability from the tests and fixtures deliberately excluded. |
Quoting only the second would report ~99% for a scan that read half a repo.
Every unread source file is attributed to exactly one reason:
skipped_by_path— intentional exclusion (tests, fixtures, examples, vendor).unscanned_by_extension— this scanner version cannot parse the language.
Languages the scanner cannot read are reported, never treated as clean. When any
turn up, a warning is printed to stderr, the table output shows an INCOMPLETE COVERAGE block, and SARIF carries a toolExecutionNotification so the run reads as
partial rather than silently green. Currently unreadable: .php, .scala, .clj,
.ex, .exs, .dart, .cpp, .c, .h, .hpp, .m, .mm, .pl, .lua, .r,
.jl, .ps1, .kts.
Observed vs inferred findings
Every finding carries an evidence_basis:
observed— backed by something in the scanned source (a detection, a provider).inferred— a governance checklist item. Nothing in the source backs it.
Inferred findings reflect absence of evidence, not evidence of absence. Table output
separates them into their own section, --severity-threshold ignores them, and SARIF
does not emit them as code-scanning alerts — a governance checklist item is not a
defect at a code location.
Output Formats
# Table output (default in terminal)
aibom-scanner scan --path . --format table
# JSON (default when piped) — includes coverage and evidence_basis
aibom-scanner scan --path . --format json > aibom.json
# SARIF for GitHub Code Scanning — observed findings only, coverage in run properties
aibom-scanner scan --path . --format sarif > results.sarif
# Fail CI on high/critical OBSERVED findings (exit 1)
aibom-scanner scan --path . --severity-threshold high
# Fail CI when the scanner could not read some languages (exit 3)
aibom-scanner scan --path . --fail-on-incomplete-coverage
| Exit code | Meaning |
|---|---|
0 |
Scan completed, no gate tripped |
1 |
Observed findings at or above --severity-threshold |
2 |
Bad arguments, unreadable path, or interrupted |
3 |
--fail-on-incomplete-coverage set and languages were unreadable |
If both gates trip, 1 wins — an observed finding is more actionable than a coverage gap.
The coverage warning always goes to stderr, so piping --format json or
--format sarif to a file yields clean, valid output.
GitHub Action
Add AI compliance scanning to every PR:
# .github/workflows/aibom-scan.yml
name: AIBOM Scan
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: saasvista/aibom-scanner@v1
with:
severity-threshold: high
AI Providers Detected
| Category | Providers |
|---|---|
| Major | OpenAI, Anthropic, Google AI, AWS Bedrock, Azure OpenAI, Cohere, Mistral, Groq |
| Open Source | HuggingFace, Together AI, Fireworks, Replicate |
| Chinese (BIS Entity List) | Zhipu AI, iFlytek, SenseTime |
| Chinese (Data Sovereignty) | DeepSeek, Alibaba Qwen, Baidu ERNIE, Moonshot, MiniMax, Baichuan, Yi |
| Agentic | CrewAI, AutoGen, LangGraph, Semantic Kernel |
| Protocol | MCP (Model Context Protocol), with each configured server listed |
| Orchestration | LangChain, LlamaIndex |
Risk Categories
| Category | Rules | Examples |
|---|---|---|
| Data Privacy | 4 | Missing DPA, data classification, prompt retention |
| Model Governance | 8 | No inventory, no versioning, supply chain risk |
| Security | 4 | Hardcoded keys, no input/output validation |
| Transparency | 3 | No AI disclosure, no decision logging |
| Accountability | 3 | No risk owner, no incident response plan |
| Bias & Fairness | 2 | No bias testing, no fairness evaluation |
| Export Compliance | 4 | BIS Entity List, data sovereignty, EU AI Act |
| Agentic AI | 5 | No HITL, no access controls, no observability |
Three more findings are built from evidence, not from a provider rule: the combined-capability finding, the unpinned MCP server and the agent tool that can execute code.
Compliance Frameworks
| Framework | Controls | Coverage |
|---|---|---|
| NIST AI RMF | 23 | GOVERN, MAP, MEASURE, MANAGE functions |
| ISO 42001 | 15 | AI management system requirements |
| EU AI Act | 11 | Articles 5-52, high-risk classification |
| OWASP LLM Top 10 (2025) | 10 | LLM01 to LLM10; 5 reachable by a finding |
| OWASP Agentic Top 10 (2026) | 10 | ASI01 to ASI10; 6 reachable by a finding |
How It Works
Your codebase
|
v
File walker (git ls-files, os.walk)
|
v
Detectors: AI SDKs and models (70 patterns), MCP servers, agent tools, secrets
|
v
Risk engine: 34 rules in 8 categories, plus 3 evidence-built findings
|
v
Control mapper: 49 controls in 3 frameworks, 20 OWASP items
|
v
Table / JSON / SARIF
Why This Exists
We scanned 5 popular open-source AI repos (470K combined GitHub stars):
- 389 AI SDK detections
- 116 compliance findings
- 0 governance controls fully mapped
One enterprise security company had a BIS Entity-Listed Chinese AI provider inherited silently through an acquisition.
If you don't know which AI SDKs, MCP servers and agent tools are in your codebase, you can't govern them.
Contributing
Contributions welcome. See CONTRIBUTING.md for guidelines.
- Add detection patterns — new AI providers, SDKs, or frameworks
- Improve risk rules — better severity calibration, new categories
- New output formats — CycloneDX, SPDX, HTML reports
- Language support — Go, Rust, Java detection improvements
License
Apache-2.0. See LICENSE.
Built by SaaSVista — AI Risk & Compliance Copilot
Metadata
Release files for aibom-scanner 1.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| aibom_scanner-1.3.0.tar.gz | 184.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| aibom_scanner-1.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 249.0 kB
Release files / aibom_scanner-1.3.0.tar.gz
| Download URL | aibom_scanner-1.3.0.tar.gz |
|---|---|
| Size | 184.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4b457e31f42d95db6d4f0967dcbb634ec99a3d19f60b9320a9669f39a1131f01
|
|
BLAKE2b-256 checksum How to use checksums |
ab5616b62366eadfedde865960da3fcedb6c501b38805b1bed42a47d28b4c916
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.
Transparency logRelease files / aibom_scanner-1.3.0-py3-none-any.whl
| Download URL | aibom_scanner-1.3.0-py3-none-any.whl |
|---|---|
| Size | 64.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1020edd1a0caf3639ecef363cd1e5bc433355e0959213f72f0b3458020b21c36
|
|
BLAKE2b-256 checksum How to use checksums |
869078e1b0d0ff19769a5a8aa0d6ae784b873ea706b1317031021f6152948e03
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.
Transparency log