Quickstart · First scan in 2 minutes

Get your first WAFPass scan result today.

Install the open-source WAFPass CLI, download the WAF++ controls, and scan a sample Terraform file. No cloud credentials, no black box — just static analysis on your Infrastructure-as-Code.

v1.1.0
WAFPass CLI
8
Pillars
83+
Controls
Docker
Compose ready
Apache 2.0
Code license

Prefer a one-liner? The installer sets up the CLI and controls for you.

macOS / Linux curl -fsSL https://waf2p.dev/install.sh | sh
Windows irm https://waf2p.dev/install.ps1 | iex
CHOOSE YOUR PATH

One clear path for every use case.

Start with the 2-minute CLI quickstart. Switch tabs when you are 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.

1

Install the CLI

WAFPass is published to PyPI as wafpass-core. Python 3.11+ is recommended.

bash
$ pip install wafpass-core
$ wafpass --version
2

Download the controls

The WAF++ controls catalog contains the 83+ rules WAFPass uses to evaluate your code.

bash
$ 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 WAFPass page and extract it to controls/.

3

Save a sample Terraform file

Create a minimal main.tf. This example deliberately leaves a public S3 bucket so WAFPass 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
}
4

Run your first check

Point WAFPass at the current directory and print the JSON summary.

bash
$ wafpass check . --output json | jq '.summary'

You should see output like this:

{
  "total_controls": 83,
  "passed": 81,
  "failed": 2,
  "pillars": {
    "security": { "passed": 18, "failed": 2 }
  }
}
81 passed — resources met the control
2 failed — resources violated a control (here, the public S3 bucket)
83 controls — total rules evaluated across 8 WAF++ pillars

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.

bash
$ 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
ServiceURLDescription
wafpass-dashboardhttp://localhost:3000React dashboard
wafpass-serverhttp://localhost:8000FastAPI REST API
Keycloak (SSO)http://localhost:8080Identity provider (admin / admin)
postgreslocalhost:5432PostgreSQL database

Once the containers are healthy, seed your first dashboard view with the demo command or by pushing a scan result:

bash
$ wafpass 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. WAFPass runs entirely on the files in the repo, so CI checks are fast and require no cloud secrets.

1

Install the pre-commit hook

Run the install script from the WAFPass repository once per clone. After that, every git commit is checked automatically.

bash
$ bash hooks/install.sh # macOS / Linux / Git Bash
$ .\hooks\install.ps1 # Windows PowerShell
2

Add WAFPass to GitHub Actions

Use the official WAFPass GitHub Action to fail pulls that introduce misconfigurations. Works with public and private repositories.

Set up WAFPass Action →

Advanced / 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.

1
Install wafpass CLI

Core evaluation engine — parse IaC, evaluate controls, generate reports

From PyPI (recommended)

bash
$ pip install wafpass-core
$ uv add wafpass-core # recommended for Python projects

From source

bash
$ 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)

bash
$ brew install git python uv
$ git clone https://github.com/WAF2p/pass.git && cd pass
$ uv pip install -e .
$ wafpass --version # verify installation
2
Install wafpass-server

FastAPI persistence layer — stores runs, waivers, secrets findings, and audit events

From PyPI (recommended)

bash
$ pip install wafpass-server
$ uv add wafpass-server # recommended for Python projects

Configure & start

bash
$ 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

3
Install wafpass-dashboard

React web dashboard — 22+ compliance views, evidence export, RBAC

bash
$ 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
TROUBLESHOOTING

Common issues & fixes.

Quick answers if something does not work on the first try.

Controls not found

If wafpass 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/