1. System mission
Security policy is written as control statements (“the system monitors and controls communications at the external boundary”, SC-7). Edge enforcement is written as WAF directives (tx.blocking_paranoia_level=3). Teams usually translate between the two by hand, and the result varies from one team to the next.
The engine closes that gap. An architect describes what the system is (one or more archetypes), what it holds (data classification) and what protects it (WAF and bot-protection vendors). The engine returns:
- a ready-to-deploy Caddy + Coraza configuration, or starting-point configuration for ModSecurity, AWS WAF, Azure WAF, F5 Advanced WAF, hCaptcha and F5 Bot Defense (Distributed Cloud or On-Prem);
- the bot-management and rate-limit policy;
- every item of the selected OWASP lists, marked required or recommended, with its controls and how the edge enforces it;
- a vendor-to-OWASP coverage table for each selected product, split into its WAF policy and its bot policy;
- the ASVS target level, the OWASP CI/CD Top 10 and SAMM practices;
- a protection coverage score per layer and per ITSG-33 control family, with per-layer scope, Implemented / N/A ticks per item, and the effect of mandatory MFA or FIDO2 / WebAuthn;
- a control-by-control ITSG-33 cross-walk (primary) with the NIST SP 800-53 Rev. 5 equivalents (secondary), with implementation text.
2. Architecture
- TLS termination. Caddy’s automatic HTTPS, TLS 1.3 only, with HSTS, covers SC-8 / SC-8(1). TLS 1.3 is the only protocol every site on this host can offer: TLS 1.2 is refused, with or without a server name.
- Rate limiting.
caddy-ratelimitzones run before the WAF, so floods and credential stuffing are dropped with429before any payload is parsed. The engine's API has its own, stricter zone. - Coraza WAF. OWASP CRS v4 in anomaly-scoring mode, plus local rules (prompt injection, auth telemetry, replay guards). If the summed score reaches the threshold, the request is denied with
403at CRS 949 (inbound) or 959 (outbound). - Routing. The engine has its own site,
owasp.dipdap.org, with its own Let’s Encrypt certificate (renewed automatically) and its own WAF route./about/*(this page) is served statically; everything else (the UI at/,/api/v1/*,/health) is proxied to the Flask app (gunicorn, WSGI). The old addresses,www.dipdap.org/OWASP/…andwww.dipdap.org/public/OWASP/…in any capitalisation, are redirected here with308, path and query kept (the docs to/about/). - Telemetry. The Caddy JSON access log and the Coraza JSON audit log are shipped to the SIEM (AU-2, AU-6, AU-12, SI-4).
3. Threat model: how data classification escalates paranoia
CRS rules are grouped by Paranoia Level. Higher levels add stricter rules: more aggressive regexes, restricted character sets, and header-consistency checks. They catch more evasions but also produce more false positives. The anomaly threshold is the score at which a request is blocked. A critical match scores 5, an error 4, a warning 3, a notice 2.
The engine sizes both settings, and the ASVS verification level, to the injury that a compromise would cause. The most sensitive class selected sets the baseline.
| Data classification | Blocking PL | Detection-only PL | Inbound threshold | ASVS | Rationale |
|---|---|---|---|---|---|
| Purely public | PL1 | PL2 | 5 | L1 | Low injury. Block clear attacks with near-zero false positives. |
| Credentials | PL2 | PL3 | 5 | L2 | Account takeover risk. Adds session-fixation and protocol-strictness rules. |
| Protected A | PL2 | PL3 | 5 | L2 | Limited injury to individuals. |
| Protected B | PL3 | PL4 | 3 | L2 | Serious injury. Strict payload parsing; a single error-level match blocks. |
| Financial / tax | PL3 | PL4 | 3 | L3 | Fraud and PCI DSS exposure. Strict fingerprinting, replay guards, edge IP reputation. |
Detection-only PL. The engine sets CRS tx.detection_paranoia_level one level above the blocking level. Rules at that level are logged but never block. Operators can then measure false positives before raising the blocking level. PL4 is only reachable through an explicit override, which the engine flags as tuning-intensive.
Archetype adjustments. Mobile and API-to-API profiles accept PUT/PATCH/DELETE and JSON. They disable CRS 920300 and, for M2M, 920320, because native and service clients routinely omit Accept and User-Agent. GenAI profiles add an inference zone, a prompt-size cap and LLM-specific local rules.
Combined archetypes. An application can be several archetypes at once. The engine then merges them: everything a legitimate client of any part needs is allowed (methods, content types, the largest body), the site-wide rate limit is the most generous of them, and the strict auth, inference and transaction zones are kept. A web portal with a chatbot therefore gets the portal's form handling and the GenAI prompt controls together.
4. OWASP standards coverage
Every item of every selected list is evaluated against the profile. An item is required when it applies (for example A07 Authentication Failures once credentials are handled) and recommended otherwise. Each item carries its engineering controls, the layer that owns it (edge, application, pipeline or mobile client) and what the primary WAF does about it at the edge, so gaps that no WAF can close are visible.
| List | Items | Selected by default for |
|---|---|---|
| OWASP Top 10 2025 (2021 selectable) | A01–A10 | Web portal, AI / GenAI portal |
| OWASP API Security Top 10 2023 | API1–API10 | Mobile portal, API-to-API |
| OWASP Mobile Top 10 2024 | M1–M10 | Mobile portal |
| OWASP Top 10 for LLM Applications 2025 (2023 selectable) | LLM01–LLM10 | AI / GenAI portal |
| OWASP Automated Threats | OAT-001 … OAT-021 (14 relevant threats) | Web portal, mobile portal, AI / GenAI portal |
Three engineering baselines are always included:
- ASVS 5.0 target level from the data classes (table above): L1 opportunistic, L2 standard, L3 advanced / critical.
- OWASP Top 10 CI/CD Security Risks (CICD-SEC-1 to CICD-SEC-10), with controls such as signed artifacts, pipeline least privilege and secret hygiene, plus the pipeline tests to run (dependency scanning, an OWASP ZAP baseline scan, a synthetic attack set).
- OWASP SAMM v2: the fifteen practices of its five business functions, each tied to what this baseline contributes.
Compliance references follow the Top 10 edition in use: input validation cites A05:2025, or A03:2021 when the 2021 list is selected.
5. Vendors
One or more products can be selected. Each gets a coverage table against every OWASP item in the profile: edge (the product mitigates it when configured), partial (it helps or detects; the application must still fix it) or none (an application or pipeline control), plus notes on what the product cannot express.
| Product | Type | Generated configuration | Typical notes |
|---|---|---|---|
| Caddy + Coraza (OWASP CRS) | WAF | coraza.conf, Caddyfile | Reference target: paranoia levels, thresholds, local rules, response inspection. |
| Apache + ModSecurity (OWASP CRS) | WAF | ModSecurity configuration | Same rule language; rate limits need mod_qos, mod_evasive or the CRS DoS plugin. |
| AWS WAF | WAF | WAFv2 web ACL (JSON) | Managed rule groups, Bot Control, ATP / ACFP, a silent browser challenge on the login page; rate limits from 10 per window; no response inspection, no paranoia levels. |
| Azure WAF | WAF | Application Gateway WAF policy (ARM template) | Default Rule Set 2.2 blocks at an anomaly score of 5 and runs at paranoia level 1 (no level 3 or 4); Bot Manager, rate limits, invisible JavaScript challenge (preview), log scrubbing; no response inspection. |
| F5 Advanced WAF | WAF | Declarative WAF policy (JSON) | Attack signatures, violations, Data Guard masking, brute-force and credential-stuffing protection without CAPTCHA, OpenAPI import; rate limits (L7 DoS) and the on-box Bot Defense profile are separate profiles. F5 BD / DI (Distributed Cloud or On-Prem) is listed under bot protection. |
| ALTCHA | Bot protection | — | Invisible proof-of-work, no cookies or tracking: the most accessible choice. |
| Google reCAPTCHA v3 / Enterprise | Bot protection | — | Invisible score; sends telemetry to a third party (privacy warning on Protected and financial data). |
| hCaptcha Enterprise (passive) | Bot protection | Page and server integration, CSP | Invisible widget verified on the server; can fall back to a visual challenge below the passive tier (accessibility warning). |
| F5 Bot Defense + Data Intelligence (BD / DI), Distributed Cloud | Bot protection | Integration plan (protected endpoints, Data Intelligence receiver) | JavaScript and Mobile SDK telemetry on protected endpoints (monitor, block or redirect), on a Distributed Cloud load balancer or a CDN connector; Data Intelligence is an add-on that delivers the data to a SIEM or bucket; third-party telemetry (privacy warning). |
| F5 Bot Defense + Data Intelligence (BD / DI), On-Prem (BIG-IP) | Bot protection | BIG-IP integration plan (connector, protected endpoints, Defense Engine API) | Runs on a BIG-IP chassis or VE (native on 17.0+, iApp on 14.1–16.x); the bot decision still comes from F5's Defense Engine API, so the BIG-IP needs outbound access, and requests continue if it does not answer in time. |
Results list the WAF products first, then the bot protection products. Each product's coverage is split into its WAF policy and its bot policy, with a line saying where each lives: Azure WAF keeps both in one WAF policy (Default Rule Set 2.2 and the Bot Manager rule set), AWS WAF in one web ACL (managed rule groups, then Bot Control and Fraud Control), F5 Advanced WAF in a security policy plus a separate on-box Bot Defense profile. Caddy + Coraza and ModSecurity have no bot management of their own and should be paired with a bot protection product.
The first selected WAF is the primary one: the edge column of the OWASP coverage, the rule table and the wording of the bot-control enforcement are written for it. coraza.conf and the Caddyfile are only generated when Caddy + Coraza is selected (or when no WAF is).
6. Decision logic
Inputs
- Archetypes (one or more): Web portal, Mobile portal, AI / GenAI portal, API-to-API
- Data classes: Public, Credentials, Protected A, Protected B, Financial / tax
- CRS version: v4.x (default) or v3.3.x (legacy)
- Threat profiles: Top 10 2025 / 2021, API Top 10 2023, Mobile Top 10 2024, LLM Top 10 2025 / 2023, Automated Threats
- Vendors: WAF products and bot-protection products (one or more)
- Authentication: MFA is mandatory; FIDO2 / WebAuthn (security keys or secure-enclave passkeys)
- Coverage score: layers in scope, Implemented / N/A ticks per item
- Optional PL override, site address, upstream
Outputs
- Summary: PL, thresholds, risk tier, ITSG-33 profile, ASVS level, protection coverage score
- CRS families and local rules, each with a reason
- Bot and rate-limit controls with OAT references
- OWASP coverage (with MFA badges), vendor mappings by WAF and bot policy, engineering baselines
- ITSG-33 and NIST SP 800-53 Rev. 5 control rows; CSV, MD and PDF downloads follow the All / ITSG-33 / NIST filter
- Vendor configuration; the full report as Markdown or PDF
The rule matrices live as JSON in the engine (CRS families, archetype defaults, bot strategies, compliance cross-walk, OWASP catalogues, vendor coverage, engineering baselines). Configuration is rendered from templates. User-supplied host names are validated against a strict host pattern before they are interpolated into the generated configuration.
Generated coraza.conf ordering
Include @coraza.conf-recommended # engine defaults
SecRuleEngine On # switch from DetectionOnly
Include @crs-setup.conf.example # CRS defaults (pass-through SecDefaultAction)
SecAction ... id:900000 / 900110 # PL + thresholds: after setup, before rules
SecRule ... id:10100-10410 # local rules: before CRS so they score ahead of 949/959
Include @owasp_crs/*.conf # CRS rule files
SecRuleRemoveById ... # archetype tuning: after the rules exist
7. Bot & automated-threat controls
Challenges are invisible (proof-of-work or a risk score) to meet WCAG 2.1 AA: the generated policy never asks for a checkbox or image puzzle. Users who fail a check get an accessible step-up, such as an email or SMS one-time code.
- All profiles: CRS 913 scanner detection (OAT-014, OAT-018), a general per-IP rate-limit zone (OAT-015), and headless-browser and honeytoken signals against scraping (OAT-011).
- Credentials: a POST rate limit on
/auth/*and account lockout (OAT-007 Credential Cracking, OAT-008 Credential Stuffing, AC-7); breached-password checks; failed-login telemetry (rule 10200) for SIEM correlation; verified sign-up with a disposable-email blocklist (OAT-019); credentials in query strings are scored. - Financial / tax: an edge IP-reputation blocklist, a transaction rate-limit zone, an
Idempotency-Keyreplay guard (rule 10300), per-session limits on payment forms (OAT-001 Carding, OAT-010 Card Cracking), reservation expiry (OAT-021 Denial of Inventory), strict fingerprinting at PL3, and logging of card-number patterns in responses. - AI / GenAI: inference rate limit, prompt-size cap (LLM10:2025 Unbounded Consumption), prompt-injection heuristics (LLM01:2025), a system-prompt canary, and blocking of AI scrapers on inference routes.
The bot protection products (ALTCHA, reCAPTCHA, hCaptcha, F5 BD / DI in Distributed Cloud or On-Prem) are listed separately from the WAFs, and each WAF’s own bot controls (for example Azure’s Bot Manager rule set or AWS Bot Control) appear under its Bot policy in section 5. Mandatory MFA does not replace these controls: it stops the account takeover, not the traffic.
WAF prompt-injection rules are a coarse, easily evaded signal. Real guardrails belong in the application: input/output classifiers, tool allow-lists and least-privilege agents.
8. Compliance cross-walk
| Requirement | OWASP reference | ITSG-33 | NIST SP 800-53 Rev. 5 | Applies when |
|---|---|---|---|---|
| Boundary protection / WAF | CRS v4 / WAF core | SC-7 | SC-7, SC-7(5), SC-7(18) | Always |
| Least privilege / object-level authorization | A01:2025 / API1 / API5:2023 | AC-6 | AC-6 | Any non-public class |
| Credential / brute-force mitigation | OAT-007 / OAT-008 | AC-7 | AC-7, IA-5(1) | Credentials |
| Identification & authentication | A07:2025 | IA-2, IA-5 | IA-2, IA-5 | Credentials |
| Input validation | A05:2025 (+API8:2023, LLM01) | SI-10, SI-16 | SI-10, SI-10(5), SI-16 | Always |
| Information leakage prevention | CRS 950-959 outbound | SI-11 | SI-11, SC-8 | Always |
| Strict session control | A01 / A07:2025 | AC-2, SC-23, AC-12 | AC-2, AC-3, SC-23, AC-12 | Protected B, Financial |
| Cryptographic transport | A04:2025 | SC-8(1) | SC-8(1) | Any non-public class |
| Protection of information at rest | A04:2025 | SC-28 | SC-28 | Protected A / B, Financial |
| API parameter & rate inspection | API4:2023 / LLM10:2025 | SC-5 | SC-5, SI-4 | Always |
| Automated threat detection & audit | A09:2025 / OAT-014 | AU-2, AU-6, AU-12, SI-4 | AU-2, AU-3, AU-6, AU-12, SI-4 | Always |
| Software supply chain & developer testing | A03:2025 / CICD-SEC-3 / CICD-SEC-9 | SA-11, SA-22 | SA-11, SA-22 | Always |
| Transaction replay resistance | OAT-001 / OAT-012 | IA-2(8) | IA-2(8), SC-23 | Financial |
| Service / partner authentication | API2 / API8:2023 | IA-3, IA-9 | IA-3, IA-9 | API-to-API |
| LLM guardrails / prompt filtering | LLM01 / LLM10:2025 | SI-10, SC-7 (GenAI profile) | SI-3, SI-10, SA-11 | AI archetype or LLM profile |
Protected B systems are mapped to GC Security Control Profile 1 (PBMM). Each generated row carries implementation text that names the configured paranoia level, thresholds, paths and limits. Assessors can therefore trace every control statement to a specific directive.
The Compliance matrix tab filters the rows by standard (All, ITSG-33 or NIST SP 800-53 Rev. 5). The CSV, MD and PDF downloads list only the standard selected; All lists both.
9. Protection coverage score
The engine gives the deployed protection profile a number. Every OWASP item of the profile is worth 3 points if it is required and 1 point if it is recommended. It earns them in full when a selected product mitigates it at the edge, half when the product only helps (partial), and nothing otherwise. Items are grouped into six layers:
| Layer | What it holds | How it is scored |
|---|---|---|
| WAF layer | Web and API risks enforced at the edge | From the selected WAF |
| Bot layer | OWASP Automated Threats | From the selected WAF and bot protection |
| Mobile layer | OWASP Mobile Top 10 | Mostly attested (client-side controls) |
| LLM layer | OWASP Top 10 for LLM Applications | Mostly attested (application guardrails) |
| Pipeline layer | Supply-chain items and the OWASP CI/CD Top 10 | Attested |
| Application layer | Access control, design, cryptography and other application controls | Partly from the WAF, otherwise attested |
Layers: not applicable and scope
All six layers are always shown. A layer with nothing to score for the profile, such as the LLM layer without the AI / GenAI Portal archetype or the Mobile layer without the Mobile Portal archetype, is marked not applicable and does not count in the overall score.
Different groups own different layers. Untick In scope on a layer to leave it out: an edge team can score only the WAF and Bot layers, a development team only the Pipeline and Application layers. Excluded layers stay listed with their own figures, but the overall score, the control families and the report count only the layers in scope, and the report names them. The choice is kept in the browser.
Tick boxes per item
The engine cannot see the application, the pipeline or the mobile client, so it never awards those points by itself. Each item on the Coverage score tab has two boxes:
| Box | Meaning | Effect on the score |
|---|---|---|
| Implemented, ticked by the operator | The control is in place in the application, pipeline or mobile client | Full points, reported as self-attested |
| Implemented, unticked on an item a selected product covers | The product has the feature but it is not enabled in this deployment | 0 points, reported as not enabled |
| N/A | The item does not apply to this application; Implemented is cleared | Left out of the score (no points earned or possible) |
Reset ticks clears all of them. The MD and PDF reports list the self-attested, not-enabled and N/A items.
Mandatory MFA and FIDO2 / WebAuthn
Two profile options describe how users log in: MFA is mandatory, and FIDO2 / WebAuthn (security keys such as YubiKey, or passkeys held in a device secure enclave or TPM), which is phishing-resistant MFA and ticks the first option too. Items MFA neutralises are scored N/A – mitigated by MFA; items it only reduces are highlighted and still scored.
| Item | MFA is mandatory | FIDO2 / WebAuthn |
|---|---|---|
| OAT-007 Credential Cracking, OAT-008 Credential Stuffing | Mitigated (N/A) | Mitigated (N/A); the credential cannot be phished or relayed |
| A07 Authentication Failures (2025, 2021) | Reduced | Reduced; also closes phishing and relay attacks, intercepted codes, push fatigue and SIM swap |
| API2 Broken Authentication | Reduced (interactive logins only) | Reduced (interactive logins only) |
| M1 Improper Credential Usage | Reduced | Reduced; no user secret in the app and the key cannot be exported |
| M3 Insecure Authentication / Authorization | Reduced | Reduced; the server verifies a device-bound assertion, but authorization checks are still needed, so M3 stays scored |
| M5 Insecure Communication | — | Reduced; an interceptor cannot capture a reusable credential |
| OAT-012 Cashing Out | — | Reduced; far fewer taken-over accounts |
| OAT-019 Account Creation | — | Reduced only when registration requires attested authenticators |
| LLM06:2025 / LLM08:2023 Excessive Agency | Reduced only when high-impact agent actions require the user’s own step-up | Same, with a request-bound passkey confirmation |
| Other LLM Top 10 risks | — | — |
MFA counts only when it is enforced on every login path (web, mobile, API, account recovery) with no opt-out (ITSG-33 IA-2(1), IA-2(2)). FIDO2 with user verification meets IA-2(6) and IA-2(8) (NIST SP 800-63B AAL3 when the key cannot be exported). Both protect the login only: a session cookie stolen afterwards still works, account recovery must not fall back to SMS, e-mail or one-time codes, and the login rate limits and bot controls stay in place. If passkeys sync through a cloud account, that account becomes part of the login’s security.
Roll-up and target
The score is also rolled up by ITSG-33 control family (AC, AU, CM, IA, SA, SC, SI). The target follows the most sensitive data class: 60% for public data, 70% with credentials, 75% for Protected A and 85% for Protected B or financial data. The score is indicative: it measures coverage. Not an ITSG-33 assessment: security assessment and authorization (SA&A) decides compliance.
10. Design corrections
The original brief and the source documents for the OWASP catalogues contained several statements that do not hold for current CRS, Coraza or the OWASP projects. The implementation corrects them:
- CRS 910 / 912 are gone in v4. IP reputation and DoS protection were removed (DoS moved to a plugin). Both also rely on persistent collections that Coraza does not provide. Rate limiting is enforced by
caddy-ratelimitand IP reputation by an edgeremote_ipblocklist. The v3.3 output marks these families as replaced. - LLM Top 10 numbering. In the 2025 edition, LLM04 is Data and Model Poisoning, resource exhaustion is LLM10 Unbounded Consumption, and LLM05 is Improper Output Handling. Mappings follow the edition selected; 2025 is the default.
admin offbreakscaddy reload. The reload command talks to the admin API. The admin API is bound tolocalhost:2019instead.- CRS was loaded without setup or tuning. The sample Caddyfile never included
crs-setupor set the PL and thresholds. Generated configs now do so, in the required order. SecDefaultAction "phase:2,deny"was removed. CRS rules useblock, which inherits the default action. A deny default turns anomaly scoring into first-match blocking. The only defaults added are pass-through ones for phases 3 and 4, because crs-setup sets phases 1–2 only and Coraza does not log rules of a phase that has no default. Without them, outbound (950–959) blocks would go unlogged.- Automated-threat identifiers follow the OWASP handbook: OAT-007 Credential Cracking, OAT-008 Credential Stuffing, OAT-001 Carding, OAT-010 Card Cracking, OAT-021 Denial of Inventory, OAT-017 Spamming.
- CI/CD risks use the project's numbering, from CICD-SEC-1 Insufficient Flow Control Mechanisms to CICD-SEC-10 Insufficient Logging and Visibility.
- SI-10(1) is “Manual Override Capability”, which is unrelated to WAF input validation. It was replaced by SI-10(5), “Restrict Inputs to Trusted Sources and Approved Formats”.
- Mobile certificate pinning is done in the app; HPKP is a retired browser header.
11. Build, test & production pipeline
The engine runs on SmartOS pkgsrc zones: the DIPDAP Caddy package (Caddy 2.11, coraza-caddy, embedded OWASP CRS v4, caddy-ratelimit) in front of a Flask app under gunicorn, as an SMF service. It is its own Caddy site, owasp.dipdap.org, with a Let’s Encrypt certificate, the shared logging and security headers, its own rate limits and its own WAF route (managed with the other routes of the host).
- Build: export the release tag and assemble a reproducible release tarball. A build host byte-compiles it with Python 3.14, checks the JSON rule matrices, validates the SMF manifest and checks the installer. The checksums are then signed with the DIPDAP package-signing key (CICD-SEC-9).
- Test: the signature and checksums are verified, the release is installed on a test zone, and the test suite runs there with the zone's own packages (every archetype, data class and CRS version, combined archetypes, all vendors and both report formats). Through Caddy, synthetic SQLi, XSS, traversal, RCE, Log4Shell and scanner requests must return 403, while legitimate UI, API and report requests return 200. The checks also confirm that the old
www.dipdap.orgaddresses redirect here, that the rest of that site still works and that the rate limit engages. - Production: runs only with the operator's go-ahead. It verifies the signature, takes a backup, re-checks the tarball's SHA-256 on the server, switches the release symlink and restarts the backend. After
caddy validateand a graceful reload, it checks over a trusted certificate that/healthand/about/return 200 and that the oldwww.dipdap.org/OWASP/address redirects (308), and rolls back automatically on failure.
12. Limitations
- Generated paths (
/auth,/inference,/transactions) are archetype defaults and must be adjusted to the real application. - A WAF complements secure code and does not replace it. Access control (A01, API1), business logic and output encoding stay the application’s responsibility; the OWASP coverage shows which items no WAF can close.
- Vendor mappings and the ModSecurity, AWS WAF, Azure WAF, F5 (Advanced WAF and Bot Defense) and hCaptcha configurations follow the vendors' public documentation as of November 2026 but have not been deployed on those products; they are starting points: verify rule-group and feature names against the vendor's current documentation before deploying.
- The compliance implementation text describes the reference Caddy + Coraza controls; with another WAF, map them through the vendor table.
- The effects of MFA and FIDO2 / WebAuthn on each OWASP item are the engine’s judgement, kept in
score.json; review them against your own authentication design. - CRS v3.3 on Coraza is best-effort legacy support. Coraza targets CRS v4.
- Any PL change should run in detection-only mode against real traffic before enforcement.