red-orbita/bulwark-gateway
Security guardrail proxy for AI agents. Intercepts and enforces policies on tool calls between users and LLM backends. Multi-tenant, fail-closed, 78+ prompt injection patterns, threat intel feeds, ...
2 stars · 0 forks
README
Bulwark Gateway Security guardrail proxy for AI agents in cloud environments. Intercepts, validates, and enforces policies on tool calls between users and LLM agents. Designed for environments where the user is potentially adversarial (fail-closed by default).
Table of Contents
Overview Architecture Features How It Compares Quick Start Configuration Summary Admin Portal Documentation Project Structure Development License
Overview Bulwark Gateway sits between your users/applications and your LLM backends (OpenAI, Ollama, vLLM, Azure, etc.). Every request passes through multiple security layers before reaching the backend:
Authentication — JWT/API key validation (fail-closed) Input Guardrail — Detects prompt injections, jailbreaks, encoding evasion IOC Check — Scans for malicious URLs/IPs/domains from threat intel feeds Tool Policy — RBAC enforcement per tenant/agent Output Filter — Redacts secrets/PII, detects indirect injection in responses Rate Limiter — Per-tenant request throttling via Redis
If any layer detects a threat, the request is blocked immediately (fail-closed).
Architecture ┌──────────────────────────────────────────────┐ │ Bulwark Gateway │ │ │ User Request ─────► Auth ► Input Guardrail ► IOC Check │ X-Tenant-ID │ │ │ X-Agent-ID │ Agent Registry │ │ (multi-backend) │ │ │ │ │ Forward to backend │ │ │ │ │ Tool Policy ◄── Response ──► Output Filter │ └──────────────┼──────────────────────────────┘ │ ┌─────────────────────────┼─────────────────────────┐ ▼ ▼ ▼ Backend A (RAG) Backend B (LLM) Backend C (Agent)
Component Port Description
Proxy 8080 Security hot path — intercepts all LLM requests
Admin Portal 8090 Web UI for configuration, monitoring, audit logs
Redis 6379 Rate limiting, state, session management
Prometheus 9090 Metrics collection
Grafana 3000 Dashboards and visualization
Full architecture details: docs/ARCHITECTURE.md
Features
Multi-tenant, multi-agent — Route requests to different backends per tenant/agent Zero-LLM hot path — Only regex + Pydantic + cache; p95 < 40ms overhead 400+ detection patterns — Prompt injection, jailbreak, encoding evasion, multilingual (ES/ZH/AR) 4 threat intel feeds — URLhaus, ThreatFox, AlienVault OTX, AbuseIPDB (+ MISP, OpenCTI, VirusTotal, Shodan) Streaming tool call buffering — Tool calls validated BEFORE yielding to client Self-protection — Blocks agents from modifying gateway config Hot-reloadable — Policies, IOCs, and agent registry reload without restart Admin Portal — Full web UI for managing all aspects of the gateway SIEM integration — Export to 13 platforms (Wazuh, Splunk, Elastic, QRadar, Datadog, etc.) Notification channels — Slack, Teams, Discord, PagerDuty, Opsgenie, Telegram, Email, Google Chat Kubernetes-native — Full K8s manifests with NetworkPolicies, HPA, PDB, Pod Security Audit trail — Immutable log of all administrative changes Enterprise secrets — Vault, AWS SM, Azure KV, GCP SM, CyberArk, SealedSecrets
How It Compares Most LLM-security tools ship as a library/SDK you embed in your app code, or as a hosted SaaS you send your prompts to. Bulwark Gateway is a self-hosted, fail-closed proxy that sits in front of any OpenAI-compatible backend — no code changes in your app, no prompts leaving your network.
Capability Bulwark Gateway LLM-security SDKs (LLM Guard, Guardrails AI, NeMo, Rebuff) Hosted SaaS (Lakera, Prompt Security, etc.)
Deployment Self-hosted proxy Library in your app Vendor cloud (API call)
Data leaves your network No No Yes (prompts sent to vendor)
Code changes required None (drop-in proxy) Yes (wrap every call) Yes (SDK/API)
Deterministic hot path Yes — regex only, no LLM Varies (some call LLMs) Vendor-side (opaque)
Added latency p95 < 40 ms (in-cluster) Varies Network round-trip to vendor
Multi-tenant / multi-agent routing Built-in No Vendor-dependent
Tool-call / MCP RBAC Yes (per-agent policies) Rare Vendor-dependent
Secret / PII output redaction Yes Some Yes
SIEM export (ECS / Wazuh / Splunk / …) Yes (13 platforms) No Limited / vendor dashboard
Standalone scan API (/v2/scan) Yes N/A (is the library) Yes (is the API)
Honest scope. Bulwark is a guardrail proxy, not a WAF and not a model-hosting platform. Classic SQLi/XSS on free-form chat input is not reliably matched by the input layer by design — those are enforced at the tool-argument layer where the payload actually reaches a DB/filesystem. See the published gap report for exactly what it does and does not catch. The hot path is pure regex (~446 input + ~150 output patterns), so detection is fast and auditable but not a substitute for a semantic classifier on every edge case — ML scanners are available as an optional layer.
Comparison reflects the common deployment model of each category; individual tools vary. Verify against each vendor's current capabilities.
Quick Start Prerequisites
Python 3.11+ Docker 24+ Kubernetes 1.28+ (production) or Docker Compose (development) Redis 7+
Kubernetes (Production — Helm) Helm is the recommended path for managed clusters (AKS/EKS/GKE). Build and push the images to your registry, then point the chart at them. <REGISTRY> is your container registry path, e.g. myacr.azurecr.io, 123456789012.dkr.ecr.eu-west-1.amazonaws.com, or ghcr.io/my-org.
1. Build and push images to your registry (run `docker login <REGISTRY>` first)
docker build -t <REGISTRY>/bulwark-gateway-proxy:1.0.0 -f Dockerfile . docker build -t <REGISTRY>/bulwark-gateway-admin:1.0.0 -f docker/Dockerfile.admin . docker push <REGISTRY>/bulwark-gateway-proxy:1.0.0 docker push <REGISTRY>/bulwark-gateway-admin:1.0.02. (Private registry only) create the pull secret the pods use
kubectl create namespace bulwark-gateway kubectl create secret docker-registry bulwark-registry \ --docker-server=<REGISTRY> \ --docker-username=<USERNAME> \ --docker-password=<PASSWORD> \ -n bulwark-gateway3. Install (app secrets are auto-generated by the chart)
helm install bulwark ./helm/bulwark-gateway \ --namespace bulwark-gateway --create-namespace \ --set backend.ip=<YOUR_LLM_BACKEND_IP> \ --set proxy.image.repository=<REGISTRY>/bulwark-gateway-proxy \ --set admin.image.repository=<REGISTRY>/bulwark-gateway-admin \ --set proxy.image.tag=1.0.0 \ --set admin.image.tag=1.0.0 \ --set 'imagePullSecrets[0].name=bulwark-registry' # omit for public registries4. Verify
kubectl get pods -n bulwark-gateway helm test bulwark -n bulwark-gateway See docs/DEPLOYMENT.md for external Redis, TLS/ingress, and full values.yaml reference. Kubernetes (Local — minikube/kind) For local clusters, k8s/deploy.sh builds images, loads them into the cluster, and applies the Kustomize manifests in one step:1. Generate secrets
./secrets/init.sh2. Build + load + deploy (auto-detects minikube/kind, generates secrets)
./k8s/deploy.shFor a remote registry instead of local load:
IMAGE_REGISTRY=<REGISTRY>/ ./k8s/deploy.sh --backend-ip <IP>
3. Verify
kubectl get pods -n bulwark-gateway Docker Compose (Development)1. Generate secrets
./secrets/init.sh2. Start all services
docker compose up -d3. Access
Proxy: http://localhost:8080
Admin: http://localhost:8090
Grafana: http://localhost:3000
Access ServicesPort-forward (K8s)
kubectl port-forward svc/proxy 8080:8080 -n bulwark-gateway kubectl port-forward svc/admin 8090:8090 -n bulwark-gatewayOr via Ingress:
Proxy: https://bulwark-gateway.local
Admin: https://admin.bulwark-gateway.local
Test the ProxyHealth check
curl http://localhost:8080/healthSend a request (API keys are passed as a Bearer token)
curl -X POST http://localhost:8080/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-api-key" \ -H "X-Tenant-ID: default" \ -H "X-Agent-ID: support-bot" \ -d '{"model": "gpt-4", "messages": [{"role": "user", "content": "Hello"}]}'Full deployment guide: docs/DEPLOYMENT.md
Configuration Summary Key Files
File Purpose
config/agents.yaml Tenant → backend mapping, auth config
config/policies/*.yaml Per-tenant security policies (RBAC)
config/notifications.yaml Notification channel definitions
config/siem/*.yaml SIEM platform templates
config/iocs.json IOC database (auto-updated by feeds)
Environment Variables
Variable Description
BULWARK_JWT_SECRET JWT signing key (or *_FILE variant)
BULWARK_REDIS_URL Redis connection URL
BULWARK_REDIS_PASSWORD Redis auth (or *_FILE variant)
BULWARK_API_KEYS Comma-separated API keys (or *_FILE)
BULWARK_WEBHOOK_ALERT_URLS Legacy notification webhooks
BULWARK_LOG_LEVEL Logging level (INFO, DEBUG, etc.)
All secrets support the *_FILE pattern — point an env var to a mounted file: env: - name: BULWARK_JWT_SECRET_FILE value: /run/secrets/jwt-secret Agent Registry Example
config/agents.yaml
tenants: example-corp: backend_url: "${BULWARK_BACKEND_URL:-http://ollama:11434}" auth_token: "${BACKEND_AUTH_TOKEN}" allowed_models: ["gpt-4", "gpt-3.5-turbo"] rate_limit_rpm: 60 Policy Exampleconfig/policies/example-corp.yaml
tenant_id: example-corp tools: allowed: - web_search - code_interpreter blocked: - file_system - shell_exec guardrails: max_tokens: 4096 block_on_injection: trueAdmin Portal Web-based management interface at / (port 8090). Pages
Page Function
Dashboard Real-time metrics, recent blocks, sparklines
Policies CRUD, validation, hot-reload
Guardrails Pattern management, sandbox testing
SIEM Export Transport configuration, connectivity testing
Notifications Alert channel management (Slack, Teams, Email, etc.)
Audit Log Immutable action history, export
Orchestrator Automated security testing
Coverage Matrix OWASP LLM Top 10 detection map
IOCs Threat intel feed management
Tenants Tenant registration and config
Agents Backend health monitoring
Access Control RBAC roles and permissions
Enrichment Attack replay browser, evasion telemetry, regex-candidate review
Skills Pre-deployment skill/MCP security scanner (SkillSpector)
Plugins Plugin hub — install, enable, security audit
Evaluation Red-team adversarial evaluation runner
Discovery Agent / shadow-AI / MCP discovery and risk assessment
Status System health (Redis, proxy, scanner, telemetry)
Default Credentials
User Role Default Password Secret Key
admin Admin bulwark-admin ADMIN_PASSWORD
security Security bulwark-security SECURITY_PASSWORD
auditor Auditor bulwark-auditor AUDITOR_PASSWORD
Change these immediately in production via K8s secrets.
Documentation Detailed guides are in the docs/ directory:
Document Description
INDEX Documentation table of contents
Architecture System design, request flow, design decisions, trust model
Deployment K8s, Docker Compose, secrets (9 providers), TLS, ingress, HA
Operations Runbook: account reset, secret rotation, backup, scaling
Troubleshooting Redis unhealthy, auth issues, SIEM, pod errors
Notifications Multi-channel alerting setup (Slack, Teams, Email, PagerDuty)
Security Hardening Living security log: audits, remediations, OWASP LLM coverage
API Reference Proxy + Admin endpoints, request/response formats
Project Structure bulwark-gateway/ ├── src/ # Proxy source code │ ├── main.py # FastAPI app entry point │ ├── models.py # Core data models (SecurityEvent, Verdict) │ ├── guardrails/ # Detection engines │ │ ├── input_guardrail.py # Input analysis (400+ patterns) │ │ ├── output_filter.py # Output redaction │ │ └── tool_policy.py # RBAC enforcement │ ├── routes/ # API routes │ │ ├── proxy.py # Main proxy flow (hot path) │ │ └── health.py # Health/metrics endpoints │ ├── telemetry/ # SIEM export + notifications │ │ ├── exporter.py # Background batch exporter │ │ ├── notifications.py # Multi-channel alert engine │ │ ├── queue.py # Non-blocking event queue │ │ └── transports/ # SIEM output adapters │ └── services/ # Shared services (IOC, registry) ├── admin/ # Admin portal │ ├── main.py # Admin FastAPI app │ ├── routes/ # Admin API routes │ ├── services/ # Auth, audit, user store │ └── templates/ # Jinja2 HTML templates (UI) ├── config/ # Configuration │ ├── agents.yaml # Agent/tenant registry │ ├── policies/ # Security policy YAML files │ ├── notifications.yaml # Notification channels │ └── siem/ # SIEM platform templates ├── docs/ # Detailed documentation ├── k8s/ # Kubernetes manifests │ ├── base/ # Core resources (deployments, services) │ ├── secrets/ # Secret generation scripts │ └── monitoring/ # Prometheus + Grafana ├── tests/ # Test suite (pytest, 1290+ tests) ├── Dockerfile # Proxy image ├── docker-compose.yml # Development environment └── pyproject.toml # Python project metadata
Development
Setup
python -m venv .venv && source .venv/bin/activate pip install -e ".[dev]"Run server
python -m uvicorn src.main:app --reload --port 8080Run tests
pytest -vLint
ruff check src/ tests/Type check
mypy src/License GPL-3.0-or-later — free to self-host, study, modify, and redistribute. See LICENSE. Contributions are welcome under the Contributor License Agreement, which lets you keep your copyright while keeping the project sustainably licensed. Licensing details and options: LICENSING.md.