Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,23 @@ ai-bom scan . -f sarif -o results.sarif

# Fail CI on critical findings
ai-bom scan . --fail-on critical --quiet

### Utility Commands

Explore and manage your AI-BOM environment with these additional commands:

```bash
# List all registered AI scanners and their current status
ai-bom list-scanners

# Compare two scan results to identify new components or risk changes
ai-bom diff scan1.json scan2.json

# Launch the interactive web dashboard for visual risk analysis
ai-bom dashboard

# Watch a directory and automatically re-scan when files change
ai-bom watch .
```

<details>
Expand Down Expand Up @@ -283,6 +300,8 @@ Scan all your n8n workflows for AI security risks — directly inside n8n. One n
3. Activate the workflow
4. Visit `http://your-n8n-url/webhook/trusera`

Looking for a step-by-step guide? Check out our [n8n Quickstart Guide](docs/guides/n8n-quickstart.md)

That's it. The node fetches all workflows, scans them, and serves an interactive HTML dashboard.

### Included Nodes
Expand Down
26 changes: 26 additions & 0 deletions docs/guides/n8n-quickstart.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# n8n + AI-BOM Integration Quickstart

Scan your n8n workflows for AI security risks and generate an AI Bill of Materials (AI-BOM) directly within your automation.

## 1. Install the Community Node
1. Open your n8n instance.
2. Go to **Settings > Community Nodes**.
3. Click **Install a community node**.
4. Enter `n8n-nodes-trusera` and click **Install**.

## 2. Create a Security Scan Workflow
A common patterns is to scan workflows and notify security teams of critical risks.

**Workflow Logic:**
`HTTP Trigger` → `AI Agent Node` → `Trusera Scan` → `Slack Notification`

### Steps:
1. **HTTP Trigger:** Set up a webhook to trigger the scan (e.g., after a deployment).
2. **AI Agent:** Your existing agent logic you wish to monitor.
3. **Trusera Scan:** - Add the **Trusera Scan** node.
- Configure your **n8n API Key** in the node credentials.
- Set the scan target to your workflow ID.
4. **Slack:** Filter for `risk_score > 70` and send an alert to your security channel.

## 3. Cross-linking
For full documentation on risk scores and CycloneDX output formats, refer to the [Main README](../../README.md).
59 changes: 59 additions & 0 deletions out-utf8.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
ΓòöΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòù
Γòæ AI-BOM AI Bill of Materials Discovery Scanner Γòæ
Γòæ by Trusera | trusera.dev Γòæ
ΓòÜΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓò¥

Scanning: X:\Open_Source_Contributions\ai-bom\verification_test.py

⠹ Running code scanner... --------------------

Found 21 AI/LLM component(s)

ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ Scan Summary ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
Γöé Target: X:\Open_Source_Contributions\ai-bom\verification_test.py Γöé
Γöé Components Found: 21 Γöé
Γöé Files Scanned: 1 Γöé
Γöé Highest Risk Score: 30/100 Γöé
Γöé Γöé
Γöé By Type: Γöé
Γöé agent_framework: 4 Γöé
Γöé llm_provider: 15 Γöé
Γöé model: 2 Γöé
Γöé Γöé
Γöé By Severity: Γöé
Γöé critical: 0 Γöé
Γöé high: 0 Γöé
Γöé medium: 4 Γöé
Γöé low: 17 Γöé
ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
AI Components Discovered
ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
Γöé # Γöé Component Γöé Type Γöé Provider Γöé Location Γöé Risk Γöé Flags Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
│ 1 │ xAI API Key │ llm_provider │ xAI │ ...ns\ai-bom\verifica… │ 30 │ hardcoded_api_key │
│ 2 │ OpenAI API Key │ llm_provider │ OpenAI │ ...s\ai-bom\verificat… │ 30 │ hardcoded_api_key │
│ 3 │ DeepSeek API Key │ llm_provider │ DeepSeek │ ...s\ai-bom\verificat… │ 30 │ hardcoded_api_key │
│ 4 │ OpenAI API Key │ llm_provider │ OpenAI │ ...s\ai-bom\verificat… │ 30 │ hardcoded_api_key │
│ 5 │ OpenAI Model │ model │ xAI │ ...ns\ai-bom\verifica… │ 5 │ unpinned_model │
│ 6 │ OpenAI Model │ model │ Alibaba │ ...s\ai-bom\verificat… │ 5 │ unpinned_model │
Γöé 7 Γöé mistralai Γöé llm_provider Γöé Mistral Γöé dependency files Γöé 0 Γöé - Γöé
Γöé 8 Γöé google-generativeai Γöé llm_provider Γöé Google Γöé dependency files Γöé 0 Γöé - Γöé
Γöé 9 Γöé openai Γöé llm_provider Γöé OpenAI Γöé dependency files Γöé 0 Γöé - Γöé
Γöé 10 Γöé langchain-core Γöé llm_provider Γöé Unknown Γöé dependency files Γöé 0 Γöé - Γöé
Γöé 11 Γöé cohere Γöé llm_provider Γöé Cohere Γöé dependency files Γöé 0 Γöé - Γöé
Γöé 12 Γöé chromadb Γöé llm_provider Γöé ChromaDB Γöé dependency files Γöé 0 Γöé - Γöé
Γöé 13 Γöé pyautogen Γöé agent_framework Γöé AutoGen Γöé dependency files Γöé 0 Γöé - Γöé
Γöé 14 Γöé langchain Γöé agent_framework Γöé LangChain Γöé dependency files Γöé 0 Γöé - Γöé
Γöé 15 Γöé google-cloud-aiplatform Γöé llm_provider Γöé Unknown Γöé dependency files Γöé 0 Γöé - Γöé
Γöé 16 Γöé langchain-openai Γöé agent_framework Γöé LangChain Γöé dependency files Γöé 0 Γöé - Γöé
Γöé 17 Γöé crewai Γöé agent_framework Γöé CrewAI Γöé dependency files Γöé 0 Γöé - Γöé
Γöé 18 Γöé anthropic Γöé llm_provider Γöé Anthropic Γöé dependency files Γöé 0 Γöé - Γöé
Γöé 19 Γöé boto3 Γöé llm_provider Γöé AWS Γöé dependency files Γöé 0 Γöé - Γöé
Γöé 20 Γöé ollama Γöé llm_provider Γöé Ollama Γöé dependency files Γöé 0 Γöé - Γöé
│ 21 │ OpenAI │ llm_provider │ OpenAI │ ...ns\ai-bom\verifica… │ 0 │ - │
ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ

Secure agent-to-agent communication with Trusera → trusera.dev


Questions or feature requests? info@trusera.dev | Full platform: trusera.dev
Binary file added out.txt
Binary file not shown.
22 changes: 18 additions & 4 deletions src/ai_bom/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@
(re.compile(r"127\.0\.0\.1:11434"), "Ollama", "completion"),
# Agent-to-Agent (A2A)
(re.compile(r"a2a\.googleapis\.com"), "Google A2A", "agent"),
# xAI
(re.compile(r"api\.x\.ai"), "xAI", "completion"),
# Alibaba
(re.compile(r"dashscope\.aliyuncs\.com"), "Alibaba", "completion"),
]

# =============================================================================
Expand Down Expand Up @@ -211,6 +215,10 @@
(re.compile(r"llama-4(-\w+)*"), "Meta"),
# DeepSeek
(re.compile(r"deepseek-\w+(-\w+)*"), "DeepSeek"),
# Alibaba Qwen
(re.compile(r"qwen(?:\d+(?:\.\d+)?)*(?:-\w+)*"), "Alibaba"),
# xAI Grok
(re.compile(r"grok-(?:\d+(?:\.\d+)?|\w+)(?:-\w+)*"), "xAI"),
]

# =============================================================================
Expand All @@ -222,10 +230,16 @@
API_KEY_PATTERNS: list[tuple[Pattern[str], str]] = [
# OpenAI (sk-proj- keys allow hyphens, must check before generic sk- pattern)
(re.compile(r"sk-proj-[a-zA-Z0-9_-]{20,}"), "OpenAI"),
# Note: DeepSeek also uses sk- prefix, causing overlap with OpenAI pattern
# The sk-[a-zA-Z0-9]{20,} pattern below will match both OpenAI and DeepSeek keys
# Additional context heuristics may be needed to distinguish between them
(re.compile(r"sk-[a-zA-Z0-9]{20,}"), "OpenAI/DeepSeek"),
# Note: DeepSeek also uses sk- prefix, causing overlap with OpenAI pattern.
# We require 'deepseek' in the surrounding context or variable name.
(
re.compile(
r"(?i)deepseek[_-]?(?:api[_-]?key|token|secret)?[\s'\"\=]+(sk-[a-zA-Z0-9]{20,})"
),
"DeepSeek",
),
# OpenAI fallback
(re.compile(r"sk-[a-zA-Z0-9]{20,}"), "OpenAI"),
# Anthropic
(re.compile(r"sk-ant-[a-zA-Z0-9-]{20,}"), "Anthropic"),
# HuggingFace
Expand Down
3 changes: 2 additions & 1 deletion src/ai_bom/detectors/endpoint_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ def detect_api_key(text: str) -> list[tuple[str, str, str]]:

for pattern, provider in API_KEY_PATTERNS:
for match in pattern.finditer(text):
key = match.group(0)
# Use the first capture group if present, otherwise the full match
key = match.group(1) if match.lastindex else match.group(0)

# Mask the key for security
if len(key) <= 12:
Expand Down
15 changes: 15 additions & 0 deletions src/ai_bom/detectors/model_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,21 @@
"llama-3": {"provider": "Meta", "deprecated": False},
"llama-2": {"provider": "Meta", "deprecated": False},
"codellama": {"provider": "Meta", "deprecated": False},
# xAI Models
"grok-2": {"provider": "xAI", "deprecated": False},
"grok-1.5": {"provider": "xAI", "deprecated": False},
"grok-1": {"provider": "xAI", "deprecated": False},
"grok-beta": {"provider": "xAI", "deprecated": False},
"grok": {"provider": "xAI", "deprecated": False},
# Alibaba Models
"qwen-max": {"provider": "Alibaba", "deprecated": False},
"qwen-plus": {"provider": "Alibaba", "deprecated": False},
"qwen-turbo": {"provider": "Alibaba", "deprecated": False},
"qwen-coder": {"provider": "Alibaba", "deprecated": False},
"qwen2.5": {"provider": "Alibaba", "deprecated": False},
"qwen2": {"provider": "Alibaba", "deprecated": False},
"qwen1.5": {"provider": "Alibaba", "deprecated": False},
"qwen": {"provider": "Alibaba", "deprecated": False},
}


Expand Down
Loading
Loading