Mjolnir
Mjolnir: AI Vulnerability Scanning Infrastructure
#Mjolnir
Mjolnir is an AI-driven security auditing framework designed for open-source Root-of-Trust (RoT) projects.
It leverages AI foundation models and adversarial review pipelines to provide continuous security assurance through periodic, incremental scanning of firmware and RTL.
#Pipeline Architecture
Mjolnir separates the declarative configuration and environment definition (Nix) from the imperative analysis execution (Python application engine).
graph TD
subgraph Nix Layer [Nix Orchestration]
A[projects/ directory] -->|1. Auto-discover| B(discovery.nix)
B --> C[flake.nix targets]
C -->|nix run .#job| D(orchestrator.nix)
D -->|2. Generate| E[Job Spec JSON]
D -->|3. Generate| F[Launcher Script]
end
subgraph Python Layer [Application Engine]
F -->|4. Execute| G(main.py)
E -.->|Reads configuration| G
G --> H[Checkout target repo]
H --> I[Discover source files]
%% Parallel File Analysis
I --> J1(Analysis Provider: File 1)
I --> J2(Analysis Provider: File 2)
I --> J3(Analysis Provider: File N)
J1 --> M[vulnerabilities.json]
J2 --> M
J3 --> M
M --> N[HTML Dashboard Generator]
N --> O[Local/GCS Output]
end
#Key Layers
- Nix Layer (Orchestration):
- Discovery (
discovery.nix): Scans theprojects/directory to automatically register every project and job configuration as a Nix package target. - Orchestration (
orchestrator.nix): When a target is executed (vianix run), it packages the job by serializing the configuration attributes into a static JSON spec file in the Nix store, and builds a launcher script.
- Discovery (
- Python Layer (Application Engine):
- Orchestrator (
main.py): Parses the serialized JSON spec, sets up the workspace directory, clones the target repository, and checks out the designated revision. - Analysis Execution: Filters files based on source directories and extensions, then runs the ADK multi-agent analysis pipeline (or mock simulation if
model = "mock"). - Reporting & Dashboarding: Compiles the findings into
vulnerabilities.jsonand generates an interactive HTML dashboard in the output directory.
- Orchestrator (
#Execution Flow
- Nix Auto-Discovery: Nix dynamically generates packages from the
projects/directory targets. - Target Launch: Running
nix run .#<job-name>executes the Nix-generated wrapper script. - JSON Spec Materialization: The launcher script runs the application engine, passing a path to the serialized JSON job specification.
- Checkout & Discovery: Python clones/updates the target repository and identifies files matching the job's scope.
- Scan Execution: The analysis engine scans the source files using the configured model and compiles the results.
- Dashboard Generation: The run's raw findings are compiled into reports and a local HTML dashboard.
#Directory Structure
- INTEGRATION_GUIDE.md: Guide for integrating Mjolnir security audits into repositories (GitHub Actions, GCS export, PR diff mode).
- app/mjolnir/: Core Python application engine, including agent tools, data models, and the ADK analysis pipeline. See Application Engine README.
- nix/: Nix infrastructure for job packaging, auto-discovery, and orchestration. See Nix README.
- projects/: Supported project definitions and job configurations. See Projects README.
output/: Generated analysis reports, run logs, and HTML dashboards.
#Supported Projects
All project definitions, job configurations, and nix setups are located under projects/. See the Projects README for more details on how to register new targets, or read the Integration Guide for step-by-step onboarding instructions.
#Getting Started
Mjolnir requires Nix with flakes enabled.
#Running an Audit
To run a predefined project audit target, execute nix run:
nix run .#<project-target>
#Examples
- Run OpenTitan ROM Audit:
nix run .#opentitan-rom - Run All OpenTitan Jobs:
nix run .#opentitan-all
#WebAssembly Dashboard & Local Viewer
Mjolnir features a WebAssembly (WASM) dashboard for browsing security audit runs, filtering findings, and visualizing vulnerability flow telemetry.
#Launching Local Web Viewer
To compile the WASM engine and start the local development server (default: http://localhost:8080):
nix run .#web-viewer
#Deploying Dashboard & Runs to GCS
Deploy static WebAssembly dashboard assets to Google Cloud Storage:
nix run .#deploy-gcs-web
Sync local analysis runs from output/v1/runs/ to Google Cloud Storage (test project runs are excluded by default):
nix run .#deploy-gcs-runs
Optional flags for run deployment:
--include-tests: Include test and mock benchmark runs.
nix run .#deploy-gcs-runs -- --include-tests
#Emitting Audit Reports (Markdown)
Convert findings from the most recent scan into GitHub-Flavored Markdown:
# Emit Markdown report for the latest run: nix run .#emit-report -- --output report.md # Specify format explicitly (defaults to markdown): nix run .#emit-report -- --output report.md --format markdown
You can also run it directly via cargo xtask:
cargo xtask emit-report --output report.md --format markdown
#Authentication
Mjolnir uses Application Default Credentials (ADC) with Google Cloud Vertex AI by default, requiring zero environment variables or secrets in production.
#Vertex AI (Production & Local Development with ADC)
-
In Production (GCP / Compute Engine / GKE): Authentication and GCP Project ID resolution are completely automatic via Application Default Credentials (ADC) and the Instance Metadata Server. No environment variables or credentials files are needed.
-
On Local Development Workstations: Authenticate once with
gcloud:gcloud auth application-default login gcloud config set project your-gcp-project-idMjolnir auto-discovers your credentials and project with zero configuration required.
#Gemini API Key (Optional / Non-GCP Fallback)
If running outside Google Cloud without ADC, you can optionally set a Gemini Developer API key:
export GEMINI_API_KEY="AIzaSy..."
#Multi-Model Support
Mjolnir supports multiple foundation models via ADK's native registry:
- Gemini:
gemini-*(via Vertex AI ADC orGEMINI_API_KEY) - Claude:
claude-*(via Vertex AI ADC) oranthropic/claude-*(via directANTHROPIC_API_KEY) - OpenAI:
gpt-*,o1-*,o3-*(viaOPENAI_API_KEY) - Ollama / Local:
ollama/<tag>connects to an external Ollama server (defaults tohttp://localhost:11434or$OLLAMA_HOST). Ensure the model is pulled beforehand (ollama pull <tag>).
nix run .#adk-ollama-test # runs against local ollama/gemma4:31b
#Testing
Mjolnir includes a suite of test targets to verify local pipelines, GCS uploads, and live LLM integration. These targets run against a synthetic git repository fixture without requiring a compiler development shell (devShell = null).
#Verification of Nix Infrastructure (Mocks)
To verify that the Nix derivations build cleanly:
nix build .#mock-smoke-test --no-link
To run a local mock test (verifies the python analysis engine and local file system hooks):
nix run .#mock-smoke-test
#Live LLM Testing
Run live scans on test fixtures using ambient ADC or optional API key:
# ADK Provider Target (Google Agent Development Kit) nix run .#adk-gemini-test # Option C: ADK Ingestion Mode nix run .#adk-gemini-ingest-test
#Running All Tests
nix run .#test-all
#Code Quality & Pre-Commit Hooks
Mjolnir enforces code formatting and quality checks across Rust (rustfmt), Markdown/JavaScript (prettier), Python (ruff), Shell (shfmt), and Starlark (buildifier).
#Running Quality Checks Manually
# Auto-format all supported files in the repository: bazel run //quality:format # Check formatting compliance: bazel test //quality:format_check # Run full quality test suite (formatting, license headers, shellcheck): bazel test //quality
#Enabling Pre-Commit Auto-Formatting
Mjolnir includes a shared Git pre-commit hook in .githooks/pre-commit that automatically formats staged files and verifies formatting before each commit.
To activate the hook in your local clone, run once:
git config core.hooksPath .githooks