Skip to content

Repository files navigation

CheeseWAF Logo

CheeseWAF

You hold the keys. AI keeps the cheese.

ALAP · AI Large-Language-Model Auto Pilot
Self-hosted, lightweight, and high-concurrency intelligent WAF.
Let AI take the helm so you can focus where it matters.

English · 简体中文

License Go Version Release CI Stars Issues


Table of Contents


Core Mechanism

Traditional regex-based WAFs rely on large signature rule sets that require high maintenance and remain susceptible to false positives or evasion techniques. Conversely, invoking LLMs synchronously on every incoming request introduces substantial latency.

CheeseWAF uses a decoupled pipeline:

  1. Inline Mitigation (Data Plane): An in-process semantic engine decodes parameters and performs Abstract Syntax Tree (AST) lexical analysis to block deterministic exploits in sub-millisecond time.
  2. Asynchronous Review (ALAP Engine): With ALAP (AI Large-Language-Model Auto Pilot), ambiguous, borderline, or embedded payloads are dispatched to a background review queue for deeper LLM inspection after responses are served, providing autonomous oversight without adding proxy latency.
  3. Dynamic Rule Synthesis: High-confidence malicious findings (high or critical) generated by the model can be automatically promoted into persistent IP, fingerprint, or signature rules applied to the data plane.

The entire system ships as a standalone binary with embedded SQLite storage, an integrated Web console, a terminal TUI tool, and a RESTful administration API.


Features

  • Semantic Analysis: Identifies SQL injection, XSS, and command injection attacks using multi-stage decoding and AST parsing instead of rigid regex patterns.
  • ALAP Asynchronous Auditing: Works with any OpenAI-compatible API or local LLM gateway in background worker queues without adding latency to live HTTP traffic.
  • 0–5 Paranoia Levels: Per-site sensitivity controls that differentiate between isolated attack payloads and patterns embedded inside long text fields, with support for temporary elevation windows (promote_seconds).
  • Access Control & Bot Mitigation: Built-in IP allow/deny lists, GeoIP blocking, client soft fingerprinting, slider CAPTCHA challenges, token-bucket rate limiting, and waiting rooms.
  • Unified Tri-Interface Management: Responsive Web UI (desktop and mobile), interactive terminal interface (waf-cli), and RESTful API backed by a single RBAC and audit logging core.
  • Zero External Dependencies: Written in pure Go with an embedded CGO-free SQLite database (modernc.org/sqlite).

Request Processing Pipeline

Solid lines denote the inline millisecond data plane; dashed lines represent post-response asynchronous ALAP auditing and rule sync:

flowchart TB
  Client[Client Request] --> Ingress[HTTP / HTTPS / HTTP3 Listener]
  Ingress --> IP{IP / Geo / Fingerprint Filter}
  IP -->|Matched Blocklist| Block[Block & Return Security Response]
  IP -->|Pass| Bot{Bot Defense / Rate Limit / Queue}
  Bot -->|Threshold Exceeded| Challenge[CAPTCHA Challenge / Queue]
  Challenge -->|Verified| Sem
  Bot -->|Pass| Sem[Semantic Analyzer Engine]
  Sem --> Shape{Payload Shape & Level Check}
  Shape -->|Isolated Attack Level 2-5| Block
  Shape -->|Embedded Payload Level 5| Block
  Shape -->|Embedded Payload Level 2-4| Pass[Pass to Origin & Async Enqueue]
  Shape -->|Clean Traffic| Origin[Forward to Upstream Origin]
  Pass --> Origin
  Pass -.->|Async Enqueue| Queue[ALAP Review Queue]
  Sem -.->|Level 5 Blocked Sample| Queue
  Queue --> LLM[Invoke Configured LLM]
  LLM --> Review{Threat Review Decision}
  Review -->|High / Critical| Rule[Auto-Generate Persistent Rules]
  Review -->|Low Risk / FP| Dismiss[Archive or Add to Allowlist]
  Rule -.->|Dynamic Rule Hot-Sync| IP
Loading

Default Network Listeners

Plane Default Address Description
Data Plane http://127.0.0.1:8080 Ingress listener for incoming Web traffic and reverse proxying
Admin Plane http://127.0.0.1:9443 Web UI, RESTful API, and setup wizard (https:// in Docker)
Cluster Plane http://127.0.0.1:9444 Node interconnect and state synchronization in cluster mode

Paranoia Levels

The paranoia level is configured per site via waf.paranoia_level (valid values: 0–5, default: 3).

Two independent knobs. waf.paranoia_level (0–5) drives the semantic engine itself — how strictly it judges payload shapes. The proxy's block/challenge thresholds come from a separate setting, protection_policy.web_attack (off / low / smart / high / strict, default smart). They are configured independently: raising paranoia_level makes the engine more sensitive, while web_attack decides what happens to a detection (severity/confidence gates, aggregate risk score, and the fail-mode when the 100 ms detection budget runs out).

In log metadata and the console, waf_policy_decision.paranoia_level reports the site's configured level (0–5) and waf_policy_decision.policy_tier reports the web_attack strategy ordinal (0–4). They are deliberately separate fields — do not read one as the other.

The analyzer inspects individual decoded parameter values (paths and parameter names remain visible) and categorizes detected attack signatures into two structural shapes:

  • Isolated Payload: The inspected parameter value consists almost entirely of exploit syntax (e.g., UNION SELECT 1,2,3, allowing minimal wrappers like @ or trailing semicolons).
  • Embedded Payload: The attack pattern appears inside ordinary text, user comments, articles, or descriptions.

Isolation classification scope (current):

  • The isolation gadget list covers PHP/JSP live shells, Log4j JNDI lookups, and short quoted/predicate SQL (≤96 runes).
  • XSS, command/RCE, SSTI, SSRF, and XXE use document shape guards, not this gadget list.
  • Only hits labeled embedded skip blocking below paranoia level 5.
  • Hits that stay unclassified still go through blockableHit evidence rules; they are not auto-treated as embedded.
  • Technical articles and writeups are not guaranteed to always pass — isolation reduces false positives for covered gadgets, it is not a blanket content pass.

Paranoia Level Matrix

Level Name Isolated Payload Embedded Payload Dynamic Elevation Mechanism & Target Scenario
0 Record Only Log only Log only No Initial baseline profiling and traffic discovery.
1 Low Monitoring Log only Log only No Staging environments, rule dry-runs, and false-positive auditing.
2 Low-Medium Block immediately Pass to origin, async review No UGC platforms, forums, rich text editors with zero false positive tolerance.
3 Standard (Default) Block immediately Pass to origin, async review No Standard production web apps and corporate portals.
4 Medium-High Block immediately Pass to origin, async review Supported (elevates to Level 5) Critical systems under probing. Temporarily elevates to Level 5 via promote_seconds.
5 Strict Mitigation Block immediately Block immediately, async review N/A (Already highest) Financial APIs, payment backends, and active emergency mitigation.

Notes:

  1. Dynamic Elevation (promote_seconds): Under Level 4, detecting embedded attack patterns can trigger a temporary elevation to Level 5 for a specified window (e.g., 300 seconds). The elevation deadline is persisted in SQLite across service restarts.
  2. Level 5 Constraints: Level 5 blocked samples are enqueued for audit with status blocked and cannot be retroactively allowed, but can be converted into permanent block rules (payloads, URLs, IPs, client fingerprints).

Deployment

CheeseWAF provides three independent deployment methods. Choose the one that suits your infrastructure:

1. Linux Deployment (Systemd Production)

Recommended for Linux physical servers and virtual machines for direct execution and low resource consumption.

Step 1: Download and Extract Release Archive

Download an Alpha- pre-release from Releases, or the matching Actions artifact. The version portion is beta on master, PreTest on canary, and dev on dev; these wildcard patterns cover every channel:

File Platform
cheesewaf-amd64-linux-*.tar.gz Linux x86_64
cheesewaf-arm64-linux-*.tar.gz Linux ARM64
cheesewaf-loong64-linux-*.tar.gz Linux LoongArch64
cheesewaf-amd64-darwin-*.tar.gz / .dmg macOS Intel
cheesewaf-arm64-darwin-*.tar.gz / .dmg macOS Apple Silicon
cheesewaf-amd64-windows-*.exe Windows x86_64 single-file CLI
cheesewaf-arm64-windows-*.exe Windows ARM64 single-file CLI
cheesewaf-amd64-windows-*.zip Windows x86_64 portable folder
cheesewaf-arm64-windows-*.zip Windows ARM64 portable folder
# Linux x86_64 example
tar -xzf cheesewaf-amd64-linux-*.tar.gz
cd cheesewaf-*

Linux ARM64 and LoongArch64 use cheesewaf-arm64-linux-*.tar.gz or cheesewaf-loong64-linux-*.tar.gz.

Step 2: Install Executable and Configure Directories

# From the extracted package directory (needs cheesewaf and web/dist):
sudo ./install-linux.sh

Or install by hand. Copy the UI files as well as the binary, otherwise /setup returns 404:

sudo install -m 0755 cheesewaf /usr/local/bin/cheesewaf
sudo ln -sf /usr/local/bin/cheesewaf /usr/local/bin/waf-cli
sudo mkdir -p /usr/share/cheesewaf/web /etc/cheesewaf /var/lib/cheesewaf /var/log/cheesewaf
sudo cp -R web/dist/. /usr/share/cheesewaf/web/
sudo cp configs/cheesewaf.yaml /etc/cheesewaf/cheesewaf.yaml
sudo useradd --system --home /var/lib/cheesewaf --shell /usr/sbin/nologin cheesewaf
sudo chown -R cheesewaf:cheesewaf /etc/cheesewaf /var/lib/cheesewaf /var/log/cheesewaf

Step 3: Configure Systemd Service

Linux archives include systemd/cheesewaf.service. Install that file. The unit grants CAP_NET_BIND_SERVICE so the non-root service can bind ports 80 and 443:

sudo cp systemd/cheesewaf.service /etc/systemd/system/cheesewaf.service

Step 4: Start and Verify Service

# Reload systemd and enable on boot
sudo systemctl daemon-reload
sudo systemctl enable --now cheesewaf

# Check service status
sudo systemctl status cheesewaf

The systemd unit keeps ProtectSystem=strict and grants the service write access only to /etc/cheesewaf, /var/lib/cheesewaf, and /var/log/cheesewaf. This lets the management API save validated configuration changes while keeping the rest of the system read-only.

The default admin listener is 127.0.0.1:9443. On the server (or over an SSH tunnel) open http://127.0.0.1:9443/setup. Loopback /setup can finish first-install without pasting a token. From another host, copy the URL from journalctl -u cheesewaf or /var/lib/cheesewaf/setup.url. Remote SERVER_IP:9443 stays closed until setup chooses a public admin strategy.

GET /api/setup returns 405; first-install status is GET /api/setup/status. Completing setup is POST /api/setup with X-CheeseWAF-Setup-Token. Login from another host still needs the console captcha; loopback API login does not.


2. Docker Deployment (Docker Compose)

Docker images are built from a git checkout (deploy/docker/Dockerfile). Release .tar.gz files are for systemd, not for docker compose without the repository. docker compose build produces linux/amd64 or linux/arm64 for the host CPU. The container runs as a non-root user (UID 10001) with a read-only root filesystem. The runtime image installs the distro CA bundle so outbound HTTPS to origins verifies certificates. Compose maps admin TLS to host loopback (127.0.0.1:9443); use an SSH tunnel or a separately hardened reverse proxy when remote access is required.

Step 1: Create Compose File

Save the following as docker-compose.yml:

services:
  cheesewaf:
    image: cheesewaf:latest
    build:
      context: .
      dockerfile: deploy/docker/Dockerfile
    user: "10001:10001"
    restart: unless-stopped
    read_only: true
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true
    tmpfs:
      - /tmp:size=32m,mode=1777,noexec,nosuid,nodev
    ports:
      - "8080:8080"
      - "9443:9443"
    volumes:
      - cheesewaf-data:/var/lib/cheesewaf
      - cheesewaf-logs:/var/log/cheesewaf
    healthcheck:
      test: ["CMD", "/usr/local/bin/cheesewaf-entrypoint", "healthcheck"]
      interval: 30s
      timeout: 5s
      retries: 3

volumes:
  cheesewaf-data:
  cheesewaf-logs:

Step 2: Start Container

# Start container in detached mode
docker compose up -d

# View logs and retrieve initial setup token
docker compose logs -f cheesewaf

Step 3: Access Admin Interface

  • Open https://<HOST_IP>:9443/setup in your browser (admin uses HTTPS with a self-signed certificate in Docker).
  • Copy the temporary onboarding token from the container startup logs.
  • Data and logs persist in cheesewaf-data and cheesewaf-logs volumes across container restarts.

3. Windows Deployment (CLI, Zip, NSIS)

Three Windows shapes. The CLI is one cheesewaf.exe. The zip adds configs, the Web UI, and the local controller. NSIS is the graphical installer.

Option A: Single-file CLI

  1. Download cheesewaf-*-windows-amd64.exe or cheesewaf-*-windows-arm64.exe.
  2. Run it as cheesewaf.exe:
.\cheesewaf-*-windows-amd64.exe serve --config .\configs\cheesewaf.yaml --data-dir .\data
.\cheesewaf-*-windows-amd64.exe status
.\cheesewaf-*-windows-amd64.exe stop

The data-plane binary does not need the installer. The admin UI is in the zip/DMG/tarball (web/dist next to the executable).

Option B: Portable folder (Zip)

  1. Download cheesewaf-*-windows-amd64.zip or cheesewaf-*-windows-arm64.zip and extract it (for example D:\CheeseWAF).
  2. Run:
.\cheesewaf.exe serve --config .\configs\cheesewaf.yaml --data-dir .\data
.\cheesewaf.exe status
.\cheesewaf.exe stop

Option C: NSIS graphical installer

  1. Run CheeseWAF-*-windows-amd64-setup.exe or CheeseWAF-*-windows-arm64-setup.exe.
  2. Follow the setup wizard. The installer registers Windows Service CheeseWAF; cheesewaf.exe serve answers Service Control Manager stop/shutdown.
  3. Uninstall keeps data\ by default.

Local Service Controller (cheesewaf-gui)

Windows releases bundle a lightweight local GUI controller bound strictly to loopback (127.0.0.1:17943):

  • Start, stop, and restart the backend WAF process.
  • Inspect process PID and operational status.
  • Open the Web management console or configuration directory directly.
  • Configure user-login autostart via the Windows Registry.

4. macOS Deployment (DMG)

  1. Download cheesewaf-arm64-darwin-*.dmg (Apple Silicon) or cheesewaf-amd64-darwin-*.dmg (Intel).
  2. Open the disk image and drag CheeseWAF into Applications.
  3. Open CheeseWAF from Launchpad or Applications. It starts the local controller (start / stop / open the Web console).
  4. Signed and notarized releases should open normally. For an ad-hoc PreTest developer build only, Control-click the app in Applications, choose Open, and confirm the one-time prompt.

Runtime files go to ~/Library/Application Support/CheeseWAF. The same payload is also in cheesewaf-*-darwin-*.tar.gz if you only want the CLI.


Quick Start

1. Initial Setup

Open the setup URL after starting the service:

  • http://127.0.0.1:9443/setup (https://127.0.0.1:9443/setup in Docker)
  • Create your administrator account and save the system key.

2. Add a Protected Site

In the Web console, go to Sites -> Add Site:

  1. Domain: Enter your public domain (e.g., example.com).
  2. Upstream: Enter the internal IP and port of your origin application (e.g., 10.0.0.10:8000).
  3. Protection Level: Select Paranoia Level 3 for standard deployments.
  4. Save: Configuration is applied immediately without restarting the service.

3. Configure AI Autopilot (ALAP)

In AI Settings:

  1. Endpoint: Enter your LLM provider endpoint (e.g., https://api.openai.com/v1).
  2. API Key & Model: Enter credentials and select the target model.
  3. Auto-Agree: Enable auto-commit for high-confidence threats if you want automated rule creation.

Management Interfaces

Interface Form Factor Primary Usage
Web Console Responsive Web application (desktop and mobile) Site configuration, rule orchestration, threat dashboards, log analysis, AI review queue
Terminal CLI Interactive TUI & command tools (waf-cli) Headless server management, configuration reloading, process status checks
RESTful API HTTP API with Bearer Token authentication CI/CD pipelines, automated deployments, custom integrations

Configuration Reference

A default data/config/cheesewaf.yaml file is generated upon first startup (reference template: configs/cheesewaf.yaml):

server:
  listen: "127.0.0.1:8080"       # Safe local default; expose intentionally
  admin_listen: "127.0.0.1:9443" # Admin plane listener
  admin_public: false             # Set true only with admin TLS configured

sites:
  - id: "site-demo"
    name: "Demo Site"
    domains: ["demo.example.com"]
    upstreams:
      - address: "192.168.1.100:8080"
        weight: 1
    waf:
      enabled: true
      mode: "block"
      paranoia_level: 3          # Paranoia Level (0–5)
      semantic_policy:
        auto_agree: true         # Auto-commit high-confidence review verdicts

protection:
  ratelimit:
    enabled: true
    default:
      requests: 100
      window: 60s
      burst: 20
  ip:
    blacklist: []
    whitelist: ["127.0.0.1", "::1"]

ai:
  enabled: true
  provider: "openai"
  api_base: "https://api.example.com/v1"
  model: "provider-default"

Site custom rules live only in sites[].waf.custom_rules. The console Rules page can import YAML/JSON: it validates and dedupes first, then replaces the site set. On failure the currently working rules stay in place and the API returns an error. The CLI can import the same document:

waf-cli --config ./data/config/cheesewaf.yaml rules example --format yaml
waf-cli --config ./data/config/cheesewaf.yaml rules import --site default --file custom_rules.yaml
waf-cli --config ./data/config/cheesewaf.yaml rules export --site default --format json

After you edit the config file, the process watches cheesewaf.yaml mtime, and SIGHUP reloads immediately. A load or compile failure keeps the previous rules.


Tech Stack

Layer Component
Data Plane Go 1.26, chi routing, quic-go (HTTP/3 support)
Detection Core In-process AST semantic analyzer, dynamic fingerprinting, token-bucket rate limiter
Review Engine Asynchronous task queues, standard Chat Completions / Messages protocol adapters
Storage Embedded SQLite (modernc.org/sqlite, pure Go), optional PostgreSQL sink
Web Console React 18, TypeScript, Vite, Tailwind CSS, shadcn/ui, TanStack Query
Terminal CLI Cobra CLI library, Bubble Tea TUI framework

Development & Testing

Requirements

  • Go 1.26 or higher
  • Node.js 24.x and npm

Build Pipeline

# 1. Clone repository
git clone https://github.com/LaokeQwQ/CheeseWAF.git
cd CheeseWAF

# 2. Build Web frontend static assets
cd web
npm ci
npm run build
cd ..

# 3. Build backend binary
go build -o bin/cheesewaf ./cmd/cheesewaf

# 4. Run
./bin/cheesewaf serve --config ./configs/cheesewaf.yaml

Verification & Corpus Tests

# Run backend tests
go test -v ./cmd/... ./internal/...
go vet ./cmd/... ./internal/...

# Frontend type checking and tests
cd web && npm run typecheck && npm test && cd ..

# Generate and replay the governed security corpus
make security-corpus

Corpus Governance

Governance runs are read-only and recursively enumerate every .jsonl or .jsonl.gz file below internal/engine/semantic/testdata/ at runtime. The pipeline is ordered as: global deduplication → structural/semantic triage → selection and cleaning → second review. It writes formal.jsonl, quarantine.jsonl, and an auditable manifest.json to a temporary directory. Git-ignored large corpora are represented as optional inputs in the manifest when absent; nested and compressed copies are not silently omitted.

make corpus-governance audits all available corpora while keeping their rows in a quarantine snapshot. make security-corpus separately builds a hash-bound formal snapshot from repository-curated sources, pins the input hashes, exact source/label/category coverage, governance policy and formal artifact hash, and requires zero hard rejects, then feeds only that snapshot to both analyzer replay and semantic evaluation. The malformed pat-sqli-00119 record remains preserved in an explicitly pinned quarantine-only file; it is not silently replaced or removed from the audit denominator. CI also requires at least 250 benign and 10,000 attack rows before applying FPR below 0.8% and TPR of at least 99% to this governed regression snapshot. This does not claim that an independent blind set or every quarantined research corpus already meets the same target.

make corpus-governance
make security-corpus

Documentation


License

This project is licensed under the Apache License 2.0.

About

A High-Peformance,Open-Source,Beauty,LLM Supported,High-SLA New Generation WAF.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages