guardrailprobe
Provider-agnostic AI guardrail benchmarking tool. Tests your guardrail layer — not your model — across 10 backends against the OWASP LLM Top 10.
What it does
guardrailprobe fires 78 attack probes at your guardrail endpoints and tells you which ones let attacks through. It produces:
- Pass/fail per probe across OWASP LLM01–LLM10 and content-moderation categories
- Side-by-side comparison of multiple backends in a single run
- Signed benchmark reports (PDF with RFC 3161 timestamp, JSON, Markdown)
- Flask dashboard for ad-hoc probe runs and report browsing
No framework lock-in. No cloud account required. Just point it at an endpoint and run.
Supported backends
| Backend | Adapter key | Notes |
|---|---|---|
| NVIDIA NeMo Guardrails | nemo |
Requires pip install guardrailprobe[nemo] (includes nemoguardrails, langchain, langchain-openai, langchain-aws, langchain-community) |
| Guardrails AI | guardrails_ai |
Regex fallback always available; SDK optional |
| Microsoft Presidio | presidio |
Requires pip install guardrailprobe[presidio] |
| Lakera Guard | lakera |
Requires LAKERA_GUARD_API_KEY |
| OpenAI Moderation | openai_moderation |
Requires OPENAI_API_KEY |
| Azure Content Safety | azure_content_safety |
Requires AZURE_CONTENT_SAFETY_KEY + endpoint |
| Azure Prompt Shields | azure_prompt_shields |
Shares credentials with azure_content_safety — no separate key |
| AWS Bedrock Guardrails | aws_bedrock |
Requires AWS_ACCESS_KEY_ID + guardrail ID |
| Meta LlamaFirewall | llama_firewall |
Requires pip install guardrailprobe[llamafirewall] |
| LLM Guard | llm_guard |
Requires pip install guardrailprobe[llm_guard] |
Adapters with missing credentials return SKIPPED gracefully — partial configurations run fine.
Installation
pip install guardrailprobe
With optional SDK extras:
# All extras
pip install "guardrailprobe[all]"
# Pick what you need
pip install "guardrailprobe[nemo,guardrails_ai,presidio]"
Skip the spaCy model download (e.g. in CI):
GUARDRAILPROBE_SKIP_SPACY=1 pip install guardrailprobe
Quick start
# 1. Set up credentials — interactive wizard (or copy .env.example to .env and edit manually)
guardrailprobe init
# 2. Check which backends are ready
guardrailprobe status
# 3. Run a benchmark (current month, all configured backends)
guardrailprobe run --output-dir ./reports
# 4. Run against specific backends only
guardrailprobe run --backends lakera,openai_moderation --output-dir ./reports
# 5. Launch the dashboard
guardrailprobe dashboard
Docker
Start the dashboard
docker compose up
Open http://localhost:8080. The container starts even without a .env file — the Setup Guide card in the dashboard lists exactly which environment variables each unready adapter needs.
Configure credentials
cp .env.example .env
# Fill in the keys for the backends you want to test, then:
docker compose up
The .env file is optional. Any variables already exported in your shell are passed through automatically via the environment: block in docker-compose.yml.
Adapter status in Docker
Here is the out-of-the-box status for each adapter and what you need to enable it:
| Adapter | Dependencies | What you need |
|---|---|---|
guardrails_ai |
None (regex fallback built-in) | Nothing — works without credentials |
presidio |
spaCy model (bundled in image) | Nothing — runs locally |
nemo |
nemoguardrails + LangChain stack (bundled) |
One LLM provider (priority order): AWS Bedrock (any credential form — IAM role, env vars, instance profile — recommended, ~8 min/run, no per-minute rate limits), OLLAMA_BASE_URL (local, GPU recommended), NEMO_OPENAI_API_KEY, OPENROUTER_API_KEY (16 req/min free tier, ~15 min/run), OPENAI_API_KEY, AZURE_OPENAI_API_KEY, or ANTHROPIC_API_KEY. Works without any LLM key in colang pattern-matching mode. |
aws_bedrock |
boto3 SDK (bundled) |
AWS_BEDROCK_GUARDRAIL_ID, AWS_DEFAULT_REGION, AWS credentials |
lakera |
None — direct REST via httpx |
LAKERA_GUARD_API_KEY |
openai_moderation |
None — direct REST via httpx |
OPENAI_API_KEY |
azure_content_safety |
None — direct REST via httpx |
AZURE_CONTENT_SAFETY_KEY + AZURE_CONTENT_SAFETY_ENDPOINT |
azure_prompt_shields |
None — direct REST via httpx |
Same as azure_content_safety — no separate key |
llama_firewall |
Volume-mounted (not in image) | See below |
llm_guard |
Volume-mounted (not in image) | See below |
LlamaFirewall (Meta PromptGuard 2)
LlamaFirewall runs a local ML model and is excluded from the Docker image to keep it lean.
Requirements: Python 3.10–3.12 on the host (PyTorch is a transitive dependency).
# 1. Install into ./site-packages on your host
# --ignore-installed avoids false conflicts with other packages in your host environment
python3.12 -m pip install llamafirewall --target ./site-packages --ignore-installed
# 2. Restart the container — the entrypoint detects the package automatically
docker compose up
On startup you will see:
[guardrailprobe] site-packages mounted — llama_firewall: YES llm_guard: NO
First run — model download (one-time): LlamaFirewall uses Meta's Llama-Prompt-Guard-2-86M model, which is gated on HuggingFace. You must:
- Accept the license at huggingface.co/meta-llama/Llama-Prompt-Guard-2-86M
- Set
HF_TOKEN=<your-token>in.envbefore starting the container
The model is cached in ./hf_models (bind-mounted at /app/hf_models inside the container). Subsequent runs load from cache and work fully offline.
PyTorch / CUDA compatibility: If the host torch version does not match the CUDA driver, the first scan raises Cannot copy out of meta tensor. The adapter automatically sets CUDA_VISIBLE_DEVICES="" to force CPU-only inference, which sidesteps this. If you still see the error, verify torch is installed in ./site-packages:
python3.12 -c "import torch; print(torch.__version__)"
If the model never loads successfully, guardrailprobe marks all LlamaFirewall probes as SKIPPED (not BLOCK) so benchmark results are not inflated.
LLM Guard (Protect AI)
LLM Guard runs PromptInjection and Toxicity scanners locally and is also excluded from the Docker image.
Requirements: Python 3.9–3.12 on the host.
# 1. Install into ./site-packages on your host
python3.12 -m pip install llm-guard --target ./site-packages --ignore-installed
# 2. Restart the container
docker compose up
On startup you will see:
[guardrailprobe] site-packages mounted — llama_firewall: NO llm_guard: YES
First run — model download (one-time): PromptInjection and Toxicity scanners download their model weights from HuggingFace on first use. No token or license is required — the models are public. Weights are cached in ./hf_models.
Scanner init failures: If llm_guard is installed but scanners fail to load (common when transformers or torch versions mismatch), the adapter logs the exact error and falls back to pattern-only detection. Probes not matched by patterns are returned as SKIPPED — not BLOCK — so benchmark results stay accurate. To diagnose:
python3.12 -c "from llm_guard.input_scanners import PromptInjection; PromptInjection()"
No environment variables are required. LLM Guard runs fully offline once models are cached.
Install both at once
python3.12 -m pip install llamafirewall llm-guard --target ./site-packages --ignore-installed
docker compose up
The container prints the detected status for each package at startup and skips any that are absent — no configuration required.
Custom HTTP guardrail (opt-in)
GenericHTTPAdapter lets you test any proprietary or self-hosted guardrail that exposes an HTTPS API. It is not registered by default — it won't appear in benchmark runs unless you register it manually:
from guardrailprobe.adapters import REGISTRY
from guardrailprobe.adapters.generic_http import GenericHTTPAdapter
REGISTRY.register(GenericHTTPAdapter())
| Variable | Required | Description |
|---|---|---|
CUSTOM_GUARDRAIL_URL |
Yes | Target endpoint — must start with https:// |
CUSTOM_GUARDRAIL_API_KEY |
No | Bearer token or API key |
CUSTOM_GUARDRAIL_AUTH_HEADER |
No | Header name for the key (default: Authorization) |
Add to .env:
CUSTOM_GUARDRAIL_URL=https://your-guardrail-api.example.com/check
CUSTOM_GUARDRAIL_API_KEY=your-key-here
# CUSTOM_GUARDRAIL_AUTH_HEADER=X-Api-Key # only needed if the API uses a non-standard header
One-shot benchmark via Docker
docker compose run --rm guardrailprobe \
guardrailprobe run --year 2026 --month 6 --output-dir /app/reports
Reports are written to the guardrailprobe_reports named volume and also to ./docs/benchmarks on the host (via the ./docs bind mount).
Ollama (local LLM for NeMo, GPU recommended)
The container uses network_mode: host so localhost:11434 inside the container reaches the host's Ollama process directly, without exposing Ollama to the LAN.
# Start Ollama on the host (separate terminal)
ollama serve
ollama pull llama3.2
# Enable in .env
echo "OLLAMA_BASE_URL=http://localhost:11434" >> .env
docker compose up
Ollama is disabled by default (OLLAMA_BASE_URL=). CPU inference with llama3.2 is too slow for NeMo's 3-call-per-probe workflow (~20 s/probe); a GPU is recommended. Without OLLAMA_BASE_URL, NeMo uses AWS Bedrock if credentials are present (priority 1 — recommended for benchmarks).
Skip the spaCy model download (CI / constrained environments)
docker compose build --build-arg SKIP_SPACY=1
Probes
78 built-in attack probes across 11 categories:
| Category | OWASP ref | Probes |
|---|---|---|
| Prompt Injection | LLM01 | 7 |
| Insecure Output Handling | LLM02 | 6 |
| Training Data Poisoning | LLM03 | 5 |
| Model Denial of Service | LLM04 | 6 |
| Supply Chain Vulnerabilities | LLM05 | 5 |
| Sensitive Info Disclosure | LLM06 | 7 |
| Insecure Plugin Design | LLM07 | 6 |
| Excessive Agency | LLM08 | 6 |
| Overreliance | LLM09 | 5 |
| Model Theft | LLM10 | 5 |
| Content Moderation | CM-001–020 | 20 |
| Total | 78 |
See METHODOLOGY.md for probe design, scoring, and reproduction steps.
Reports
Each guardrailprobe run produces three artifacts in the output directory:
reports/
benchmark_2026_06.pdf # Signed PDF with RFC 3161 timestamp
benchmark_2026_06.json # Machine-readable full results
benchmark_2026_06.md # Human-readable summary
To sign reports with your own certificate:
guardrailprobe cert generate # self-signed P12 for testing
guardrailprobe cert show # inspect the active signing cert
guardrailprobe cert verify report.pdf # verify an existing report
Set GUARDRAIL_SIGNING_KEY_P12 to the path of your P12 file.
Configuration
Choose either approach — both produce the same .env file.
Option A — Interactive wizard (recommended)
guardrailprobe init
Walks through each backend and prompts for keys. Press Enter to skip any adapter you don't have credentials for. Writes only what you enter to .env.
Option B — Edit manually
cp .env.example .env
# Open .env and fill in the keys for the backends you want to test
Key variables
| Variable | Backend |
|---|---|
LAKERA_GUARD_API_KEY |
Lakera Guard |
OPENAI_API_KEY |
OpenAI Moderation; NeMo fallback (priority 5) |
AZURE_CONTENT_SAFETY_ENDPOINT + AZURE_CONTENT_SAFETY_KEY |
Azure Content Safety and Azure Prompt Shields |
AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY |
AWS Bedrock Guardrails; NeMo LLM via Bedrock (priority 1, recommended — ~8 min/run, no rate limits) |
AWS_BEDROCK_GUARDRAIL_ID + AWS_DEFAULT_REGION |
AWS Bedrock Guardrails — guardrail ID and region |
CUSTOM_GUARDRAIL_URL |
Generic HTTP adapter — any HTTPS guardrail endpoint (opt-in) |
CUSTOM_GUARDRAIL_API_KEY |
Generic HTTP adapter — optional API key |
GUARDRAIL_SIGNING_KEY_P12 |
PDF signing certificate path |
NeMo-specific variables
| Variable | Default | Description |
|---|---|---|
NEMO_BEDROCK_MODEL |
amazon.nova-pro-v1:0 |
Bedrock model for NeMo intent classification (priority 1 — recommended) |
NEMO_OPENAI_API_KEY |
— | Dedicated OpenAI key for NeMo only (priority 3); avoids sharing with OpenAI Moderation backend |
NEMO_OPENAI_MODEL |
gpt-4o-mini |
Model when using OpenAI or OpenRouter as NeMo LLM |
OPENROUTER_API_KEY |
— | OpenRouter free-tier LLM for NeMo (priority 4, 16 req/min limit — ~15 min/run) |
OPENROUTER_MODEL |
nvidia/nemotron-3-nano-30b-a3b:free |
Model when using OpenRouter |
OLLAMA_BASE_URL |
(empty) | Local Ollama endpoint for NeMo (priority 2); set to http://localhost:11434 to enable. Requires GPU — CPU inference is too slow for NeMo's 3-call-per-probe flow |
OLLAMA_MODEL |
llama3.2 |
Ollama model name |
AZURE_OPENAI_API_KEY + AZURE_OPENAI_ENDPOINT |
— | Azure OpenAI as NeMo LLM (priority 6) |
ANTHROPIC_API_KEY |
— | Anthropic Claude as NeMo LLM via LangChain (priority 7) |
After either option, verify which backends are ready:
guardrailprobe status
Python API
from guardrailprobe import GuardrailBackend
from guardrailprobe.runner import RedTeamRunner
from guardrailprobe.probes import ProbeLibrary, AttackCategory
runner = RedTeamRunner()
library = ProbeLibrary()
# Run all probes against one backend
report = runner.run(GuardrailBackend.LAKERA, library.all_probes())
print(f"Pass rate: {report.pass_rate:.1%}")
# Compare backends
comparison = runner.compare_backends(
[GuardrailBackend.LAKERA, GuardrailBackend.OPENAI_MODERATION],
library.all_probes(),
)
print(f"Best overall: {comparison.best_overall}")
# Filter probes
injection_probes = library.get_by_category(AttackCategory.PROMPT_INJECTION)
critical_probes = library.get_by_severity("critical")
cm_probes = library.get_content_moderation_probes()
Development
GUARDRAILPROBE_SKIP_SPACY=1 pip install -e ".[dev]"
pytest tests/ -v
ruff check guardrailprobe/ tests/
License
Apache-2.0 — see LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file guardrailprobe-0.1.3.tar.gz.
File metadata
- Download URL: guardrailprobe-0.1.3.tar.gz
- Upload date:
- Size: 175.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9571dafef51335922cfb521e871ca8f18453e3483c8ea3359cb07fdd7190b2e6
|
|
| MD5 |
010c6872bdce1dc46fdb5ee21d185de5
|
|
| BLAKE2b-256 |
42ed4df778e8d4c25d3a4108defa06b1fdcee18606aa79c093ed71e903c27106
|
Provenance
The following attestation bundles were made for guardrailprobe-0.1.3.tar.gz:
Publisher:
release.yml on askuma/guardrailprobe
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
guardrailprobe-0.1.3.tar.gz -
Subject digest:
9571dafef51335922cfb521e871ca8f18453e3483c8ea3359cb07fdd7190b2e6 - Sigstore transparency entry: 2095638943
- Sigstore integration time:
-
Permalink:
askuma/guardrailprobe@7e7eeef4c0f5d0c0d04821c640a928c7dd3adaa1 -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/askuma
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7e7eeef4c0f5d0c0d04821c640a928c7dd3adaa1 -
Trigger Event:
push
-
Statement type:
File details
Details for the file guardrailprobe-0.1.3-py3-none-any.whl.
File metadata
- Download URL: guardrailprobe-0.1.3-py3-none-any.whl
- Upload date:
- Size: 114.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d500e8e726c9e748b5fa869a69dc076f77405cb71d8808f8b9d211048df2f8d2
|
|
| MD5 |
85314285788080457d911b4d19b177bb
|
|
| BLAKE2b-256 |
65f95fb7f04058627f66a5dbf4d692f11033f73e82203adf69a3705da2f03022
|
Provenance
The following attestation bundles were made for guardrailprobe-0.1.3-py3-none-any.whl:
Publisher:
release.yml on askuma/guardrailprobe
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
guardrailprobe-0.1.3-py3-none-any.whl -
Subject digest:
d500e8e726c9e748b5fa869a69dc076f77405cb71d8808f8b9d211048df2f8d2 - Sigstore transparency entry: 2095639321
- Sigstore integration time:
-
Permalink:
askuma/guardrailprobe@7e7eeef4c0f5d0c0d04821c640a928c7dd3adaa1 -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/askuma
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7e7eeef4c0f5d0c0d04821c640a928c7dd3adaa1 -
Trigger Event:
push
-
Statement type: