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, RBAC tool policies, output filtering, SIEM integration. Zero-LLM hot path, p95 < 40ms. Admin Portal included. Kubernetes-native.

5

stars

260

commits

Python

primary language

Sep 6, 2026

updated

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

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:

  1. Authentication — JWT/API key validation (fail-closed)
  2. Input Guardrail — Detects prompt injections, jailbreaks, encoding evasion
  3. IOC Check — Scans for malicious URLs/IPs/domains from threat intel feeds
  4. Tool Policy — RBAC enforcement per tenant/agent
  5. Output Filter — Redacts secrets/PII, detects indirect injection in responses
  6. 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)
ComponentPortDescription
Proxy8080Security hot path — intercepts all LLM requests
Admin Portal8090Web UI for configuration, monitoring, audit logs
Redis6379Rate limiting, state, session management
Prometheus9090Metrics collection
Grafana3000Dashboards 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.

CapabilityBulwark GatewayLLM-security SDKs (LLM Guard, Guardrails AI, NeMo, Rebuff)Hosted SaaS (Lakera, Prompt Security, etc.)
DeploymentSelf-hosted proxyLibrary in your appVendor cloud (API call)
Data leaves your networkNoNoYes (prompts sent to vendor)
Code changes requiredNone (drop-in proxy)Yes (wrap every call)Yes (SDK/API)
Deterministic hot pathYes — regex only, no LLMVaries (some call LLMs)Vendor-side (opaque)
Added latencyp95 < 40 ms (in-cluster)VariesNetwork round-trip to vendor
Multi-tenant / multi-agent routingBuilt-inNoVendor-dependent
Tool-call / MCP RBACYes (per-agent policies)RareVendor-dependent
Secret / PII output redactionYesSomeYes
SIEM export (ECS / Wazuh / Splunk / …)Yes (13 platforms)NoLimited / vendor dashboard
Standalone scan API (/v2/scan)YesN/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.0

# 2. (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-gateway

# 3. 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 registries

# 4. 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.sh

# 2. Build + load + deploy (auto-detects minikube/kind, generates secrets)
./k8s/deploy.sh

# For 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.sh

# 2. Start all services
docker compose up -d

# 3. Access
#    Proxy:  http://localhost:8080
#    Admin:  http://localhost:8090
#    Grafana: http://localhost:3000

Access Services

# Port-forward (K8s)
kubectl port-forward svc/proxy 8080:8080 -n bulwark-gateway
kubectl port-forward svc/admin 8090:8090 -n bulwark-gateway

# Or via Ingress:
#   Proxy:  https://bulwark-gateway.local
#   Admin:  https://admin.bulwark-gateway.local

Test the Proxy

# Health check
curl http://localhost:8080/health

# Send 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

FilePurpose
config/agents.yamlTenant → backend mapping, auth config
config/policies/*.yamlPer-tenant security policies (RBAC)
config/notifications.yamlNotification channel definitions
config/siem/*.yamlSIEM platform templates
config/iocs.jsonIOC database (auto-updated by feeds)

Environment Variables

VariableDescription
BULWARK_JWT_SECRETJWT signing key (or *_FILE variant)
BULWARK_REDIS_URLRedis connection URL
BULWARK_REDIS_PASSWORDRedis auth (or *_FILE variant)
BULWARK_API_KEYSComma-separated API keys (or *_FILE)
BULWARK_WEBHOOK_ALERT_URLSLegacy notification webhooks
BULWARK_LOG_LEVELLogging 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 Example

# config/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: true

Admin Portal

Web-based management interface at / (port 8090).

Pages

PageFunction
DashboardReal-time metrics, recent blocks, sparklines
PoliciesCRUD, validation, hot-reload
GuardrailsPattern management, sandbox testing
AllowlistPer-tenant/agent allow-exceptions (BLOCK→WARN, auditable)
Security EventsDurable event history, per-tenant analytics, retention
SIEM ExportTransport configuration, connectivity testing
NotificationsAlert channel management (Slack, Teams, Email, etc.)
Audit LogImmutable action history, export
OrchestratorAutomated security testing
Coverage MatrixOWASP LLM Top 10 detection map
IOCsThreat intel feed management
TenantsTenant registration and config
AgentsBackend health monitoring
Access ControlRBAC roles and permissions
EnrichmentAttack replay browser, evasion telemetry, regex-candidate review
SkillsPre-deployment skill/MCP security scanner (SkillSpector)
PluginsInstall (local path / Git URL), enable, security audit
EvaluationRed-team adversarial evaluation runner
DiscoveryAgent / shadow-AI / MCP discovery and risk assessment
StatusSystem health (Redis, proxy, scanner, telemetry)

Default Credentials

UserRoleDefault PasswordSecret Key
adminAdminbulwark-adminADMIN_PASSWORD
securitySecuritybulwark-securitySECURITY_PASSWORD
auditorAuditorbulwark-auditorAUDITOR_PASSWORD

Change these immediately in production via K8s secrets.


Documentation

Detailed guides are in the docs/ directory:

DocumentDescription
INDEXDocumentation table of contents
ArchitectureSystem design, request flow, design decisions, trust model
DeploymentK8s, Docker Compose, secrets (9 providers), TLS, ingress, HA
OperationsRunbook: account reset, secret rotation, backup, scaling
TroubleshootingRedis unhealthy, auth issues, SIEM, pod errors
NotificationsMulti-channel alerting setup (Slack, Teams, Email, PagerDuty)
Security HardeningLiving security log: audits, remediations, OWASP LLM coverage
API ReferenceProxy + 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 8080

# Run tests
pytest -v

# Lint
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.

Contributors

jorodriguezmo

258 commits

red-orbita

2 commits

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, RBAC tool policies, output filtering, SIEM integration. Zero-LLM hot path, p95 < 40ms. Admin Portal included. Kubernetes-native.

5

stars

260

commits

Python

primary language

Sep 6, 2026

updated

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

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:

  1. Authentication — JWT/API key validation (fail-closed)
  2. Input Guardrail — Detects prompt injections, jailbreaks, encoding evasion
  3. IOC Check — Scans for malicious URLs/IPs/domains from threat intel feeds
  4. Tool Policy — RBAC enforcement per tenant/agent
  5. Output Filter — Redacts secrets/PII, detects indirect injection in responses
  6. 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)
ComponentPortDescription
Proxy8080Security hot path — intercepts all LLM requests
Admin Portal8090Web UI for configuration, monitoring, audit logs
Redis6379Rate limiting, state, session management
Prometheus9090Metrics collection
Grafana3000Dashboards 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.

CapabilityBulwark GatewayLLM-security SDKs (LLM Guard, Guardrails AI, NeMo, Rebuff)Hosted SaaS (Lakera, Prompt Security, etc.)
DeploymentSelf-hosted proxyLibrary in your appVendor cloud (API call)
Data leaves your networkNoNoYes (prompts sent to vendor)
Code changes requiredNone (drop-in proxy)Yes (wrap every call)Yes (SDK/API)
Deterministic hot pathYes — regex only, no LLMVaries (some call LLMs)Vendor-side (opaque)
Added latencyp95 < 40 ms (in-cluster)VariesNetwork round-trip to vendor
Multi-tenant / multi-agent routingBuilt-inNoVendor-dependent
Tool-call / MCP RBACYes (per-agent policies)RareVendor-dependent
Secret / PII output redactionYesSomeYes
SIEM export (ECS / Wazuh / Splunk / …)Yes (13 platforms)NoLimited / vendor dashboard
Standalone scan API (/v2/scan)YesN/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.0

# 2. (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-gateway

# 3. 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 registries

# 4. 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.sh

# 2. Build + load + deploy (auto-detects minikube/kind, generates secrets)
./k8s/deploy.sh

# For 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.sh

# 2. Start all services
docker compose up -d

# 3. Access
#    Proxy:  http://localhost:8080
#    Admin:  http://localhost:8090
#    Grafana: http://localhost:3000

Access Services

# Port-forward (K8s)
kubectl port-forward svc/proxy 8080:8080 -n bulwark-gateway
kubectl port-forward svc/admin 8090:8090 -n bulwark-gateway

# Or via Ingress:
#   Proxy:  https://bulwark-gateway.local
#   Admin:  https://admin.bulwark-gateway.local

Test the Proxy

# Health check
curl http://localhost:8080/health

# Send 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

FilePurpose
config/agents.yamlTenant → backend mapping, auth config
config/policies/*.yamlPer-tenant security policies (RBAC)
config/notifications.yamlNotification channel definitions
config/siem/*.yamlSIEM platform templates
config/iocs.jsonIOC database (auto-updated by feeds)

Environment Variables

VariableDescription
BULWARK_JWT_SECRETJWT signing key (or *_FILE variant)
BULWARK_REDIS_URLRedis connection URL
BULWARK_REDIS_PASSWORDRedis auth (or *_FILE variant)
BULWARK_API_KEYSComma-separated API keys (or *_FILE)
BULWARK_WEBHOOK_ALERT_URLSLegacy notification webhooks
BULWARK_LOG_LEVELLogging 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 Example

# config/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: true

Admin Portal

Web-based management interface at / (port 8090).

Pages

PageFunction
DashboardReal-time metrics, recent blocks, sparklines
PoliciesCRUD, validation, hot-reload
GuardrailsPattern management, sandbox testing
AllowlistPer-tenant/agent allow-exceptions (BLOCK→WARN, auditable)
Security EventsDurable event history, per-tenant analytics, retention
SIEM ExportTransport configuration, connectivity testing
NotificationsAlert channel management (Slack, Teams, Email, etc.)
Audit LogImmutable action history, export
OrchestratorAutomated security testing
Coverage MatrixOWASP LLM Top 10 detection map
IOCsThreat intel feed management
TenantsTenant registration and config
AgentsBackend health monitoring
Access ControlRBAC roles and permissions
EnrichmentAttack replay browser, evasion telemetry, regex-candidate review
SkillsPre-deployment skill/MCP security scanner (SkillSpector)
PluginsInstall (local path / Git URL), enable, security audit
EvaluationRed-team adversarial evaluation runner
DiscoveryAgent / shadow-AI / MCP discovery and risk assessment
StatusSystem health (Redis, proxy, scanner, telemetry)

Default Credentials

UserRoleDefault PasswordSecret Key
adminAdminbulwark-adminADMIN_PASSWORD
securitySecuritybulwark-securitySECURITY_PASSWORD
auditorAuditorbulwark-auditorAUDITOR_PASSWORD

Change these immediately in production via K8s secrets.


Documentation

Detailed guides are in the docs/ directory:

DocumentDescription
INDEXDocumentation table of contents
ArchitectureSystem design, request flow, design decisions, trust model
DeploymentK8s, Docker Compose, secrets (9 providers), TLS, ingress, HA
OperationsRunbook: account reset, secret rotation, backup, scaling
TroubleshootingRedis unhealthy, auth issues, SIEM, pod errors
NotificationsMulti-channel alerting setup (Slack, Teams, Email, PagerDuty)
Security HardeningLiving security log: audits, remediations, OWASP LLM coverage
API ReferenceProxy + 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 8080

# Run tests
pytest -v

# Lint
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.

Contributors

jorodriguezmo

258 commits

red-orbita

2 commits

Languages

Python

76.8%

HTML

17.3%

Shell

2.6%