First scan, in 2 minutes.
Install the open-source WOMBATpass CLI, download the Wombat controls, and scan a sample Terraform file. No cloud credentials, no black box, just static analysis on your Infrastructure-as-Code.
Your code never leaves the room.
WOMBATpass parses Terraform plans locally — no cloud account, no upload, no network round trip. Review the plan and the lock file on an air-gapped machine, then decide what to send.
Static analysis only: the CLI reads your Infrastructure-as-Code and reports findings. Nothing is executed, and nothing leaves your machine unless you push it to your own server.
Prefer a one-liner? The installer sets up the CLI and controls for you.
$curl -fsSL https://wombat-cli.dev/install.sh | sh
$irm https://wombat-cli.dev/install.ps1 | iex
One clear path for every use case.
Start with the 2-minute CLI quickstart. Switch tabs when you're ready for the dashboard, CI, or manual setup.
Get your first result in 2 minutes.
Follow the four steps below. Each command is designed to give you a guaranteed, readable result on your first try.
Install the CLI
WOMBATpass is published to PyPI as wafpass-core. Python 3.11+ is recommended.
$pip install wafpass-core
$wombat --version
Download the controls
The Wombat controls catalog contains the 100+ rules WOMBATpass uses to evaluate your code.
$git clone https://github.com/WAF2p/framework.git controls-src
$cp -r controls-src/modules/controls/controls ./controls
Recommended: clone the controls repo. Alternative: download the controls zip from the WOMBATpass page and extract it to controls/.
Save a sample Terraform file
Create a minimal main.tf. This example deliberately leaves a public S3 bucket so WOMBATpass has something to flag.
provider "aws" {
region = "eu-central-1"
}
resource "aws_s3_bucket" "public" {
bucket = "wafpp-first-check-demo"
}
resource "aws_s3_bucket_public_access_block" "public" {
bucket = aws_s3_bucket.public.id
block_public_acls = false
block_public_policy = false
ignore_public_acls = false
restrict_public_buckets = false
}
Run your first check
Point WOMBATpass at the current directory and print the JSON summary.
$wombat check . --output json | jq '.summary'
You should see output like this:
{
"total_controls": 100,
"passed": 98,
"failed": 2,
"pillars": {
"security": { "passed": 18, "failed": 2 }
}
}
Share it: turn this JSON into a WOMBATpass score card →
The same result, visualized, if you add the dashboard later:
Run the full dashboard locally.
The WAF2p/pass monorepo ships a unified docker-compose.yml. It brings up the CLI, server, dashboard, PostgreSQL, and Keycloak in one command.
$git clone https://github.com/WAF2p/pass.git
$cd pass
$cp .env.example .env
$# Edit .env, set POSTGRES_PASSWORD, WAFPASS_JWT_SECRET, etc.
$docker compose up -d
| Service | URL | Description |
|---|---|---|
| wafpass-dashboard | http://localhost:3000 | React dashboard |
| wafpass-server | http://localhost:8000 | FastAPI REST API |
| Keycloak (SSO) | http://localhost:8080 | Identity provider (admin / admin) |
| postgres | localhost:5432 | PostgreSQL database |
Once the containers are healthy, seed your first dashboard view with the demo command or by pushing a scan result:
$wombat demo # creates sample data and opens the dashboard
$open http://localhost:3000
View full docker-compose.yml
services:
# ── PostgreSQL ────────────────────────────────────────────
postgres:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER:-wafpass}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-wafpass}
POSTGRES_DB: ${POSTGRES_DB:-wafpass}
volumes:
- postgres_data:/var/lib/postgresql/data
- ./keycloak/init.sql:/docker-entrypoint-initdb.d/01-keycloak-db.sql:ro
ports:
- "${POSTGRES_PORT:-5432}:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-wafpass} -d ${POSTGRES_DB:-wafpass}"]
interval: 5s
timeout: 5s
retries: 10
# ── wafpass-server ────────────────────────────────────────
wafpass-server:
build:
context: .
dockerfile: wafpass-server/Dockerfile
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
environment:
DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-wafpass}:${POSTGRES_PASSWORD:-wafpass}@postgres:5432/${POSTGRES_DB:-wafpass}
WAFPASS_ENV: ${WAFPASS_ENV:-local}
CORS_ORIGINS: ${API_URL:-http://localhost:3000},http://wafpass-dashboard,http://cloud.waf2p
WAFPASS_CONTROLS_DIR: ${WAFPASS_CONTROLS_DIR:-/app/controls}
WAFPASS_JWT_SECRET: ${WAFPASS_JWT_SECRET:-change-me-in-production}
WAFPASS_JWT_EXPIRE_MINUTES: ${WAFPASS_JWT_EXPIRE_MINUTES:-60}
WAFPASS_JWT_REFRESH_DAYS: ${WAFPASS_JWT_REFRESH_DAYS:-7}
WAFPASS_ADMIN_USERNAME: ${WAFPASS_ADMIN_USERNAME:-admin}
WAFPASS_ADMIN_PASSWORD: ${WAFPASS_ADMIN_PASSWORD:-admin}
WAFPASS_ADMIN_ROLE: ${WAFPASS_ADMIN_ROLE:-admin}
WAFPASS_API_KEY: ${WAFPASS_API_KEY:-key}
ports:
- "8000:8000"
# ── Keycloak (SSO / IdP — dev mode) ──────────────────────
keycloak:
image: quay.io/keycloak/keycloak:26.1
command: start-dev
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
environment:
KC_DB: postgres
KC_DB_URL: jdbc:postgresql://postgres:5432/${KEYCLOAK_DB:-keycloak}
KC_DB_USERNAME: ${KEYCLOAK_DB_USER:-keycloak}
KC_DB_PASSWORD: ${KEYCLOAK_DB_PASSWORD:-keycloak}
KEYCLOAK_ADMIN: ${KEYCLOAK_ADMIN_USER:-admin}
KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD:-admin}
KC_HTTP_ENABLED: "true"
KC_HOSTNAME_STRICT: "false"
KC_HEALTH_ENABLED: "true"
ports:
- "${KEYCLOAK_PORT:-8080}:8080"
healthcheck:
test: ["CMD-SHELL", "curl -sf http://localhost:8080/health/ready || exit 1"]
interval: 15s
timeout: 5s
retries: 20
start_period: 60s
# ── wafpass-dashboard ─────────────────────────────────────
wafpass-dashboard:
build:
context: ./wafpass-dashboard
dockerfile: Dockerfile
restart: unless-stopped
depends_on:
- wafpass-server
ports:
- "3000:80"
volumes:
postgres_data:
Add to CI / pre-commit.
Block non-compliant infrastructure before it reaches your main branch. WOMBATpass runs entirely on the files in the repo, so CI checks are fast and require no cloud secrets.
Install the pre-commit hook
Run the install script from the WOMBATpass repository once per clone. After that, every git commit is checked automatically.
$bash hooks/install.sh # macOS / Linux / Git Bash
$.\hooks\install.ps1 # Windows PowerShell
Add WOMBATpass to GitHub Actions
Use the official WOMBATpass GitHub Action to fail pulls that introduce misconfigurations. Works with public and private repositories.
Set up WOMBATpass ActionAdvanced / manual setup.
Install only the components you need. Start with the CLI for CI/CD, then add the server and dashboard when you need persistence and visual exploration.
Install wombat CLI
Core evaluation engine: parse IaC, evaluate controls, generate reports.
From PyPI (recommended)
$pip install wafpass-core
$uv add wafpass-core # recommended for Python projects
From source
$git clone https://github.com/WAF2p/pass.git
$cd pass
$uv pip install -e . # recommended
$pip install -e ".[pdf]" # with PDF report support
macOS (Apple M-series)
$brew install git python uv
$git clone https://github.com/WAF2p/pass.git && cd pass
$uv pip install -e .
$wombat --version # verify installation
Install wafpass-server
FastAPI persistence layer: stores runs, waivers, secret findings, and audit events.
From PyPI (recommended)
$pip install wafpass-server
$uv add wafpass-server # recommended for Python projects
Configure & start
$cp .env.example .env # set DATABASE_URL and JWT secret
$alembic upgrade head # apply database migrations
$uvicorn wafpass_server.main:app --reload --port 8000
API docs available at http://localhost:8000/api/docs
Install wafpass-dashboard
React web dashboard: 22+ compliance views, evidence export, RBAC.
$git clone https://github.com/WAF2p/wafpass-dashboard.git
$cd wafpass-dashboard
$npm install
$cp .env.example .env.local # set VITE_API_URL
$npm run dev # dev server at http://localhost:5173
Common issues & fixes.
Quick answers if something doesn't work on the first try.
Controls not found
If wombat check reports "controls directory not found", the CLI will display download instructions automatically. Make sure the controls/ folder sits next to where you run scans.
Port already in use
Use a different port for the server or dashboard:
$uvicorn wafpass_server.main:app --port 8001
$npm run dev -- --port 5174
Database connection errors
Verify PostgreSQL is running and your DATABASE_URL is correct:
$psql $DATABASE_URL -c "SELECT 1"
Docker build fails
Ensure all three repositories are cloned side-by-side in the same parent directory when building from source:
$ls -1
pass/
wafpass-server/
wafpass-dashboard/
You're in control.
Local by default, explicit by design. You choose what is scanned, what is stored, and what leaves your machine — WOMBATpass never needs your cloud credentials.
You ran your first check. What next?
Pick the next step that matches your role: deepen framework knowledge, wire WOMBATpass into CI/CD, or explore the full visual dashboard.