Under attack mode for OpenWAF Verify
Under attack mode puts the browser challenge in front of the whole zone while it is under an application-layer flood or a scraping wave. Every browser navigation without a valid __waf_pass gets the proof-of-work page («Checking your browser before accessing www.example.com»), on api.* names too, and every other request without a pass gets 403 with {"error":"challenge_required",…} and OpenWAF-Mitigated: challenge, never the HTML page. By default the challenge is one bit harder than the name's usual one, and you can also shorten the pass lifetime.
Paths in exempt_paths (webhooks, payment callbacks), IP and ASN allow rules, WAF exceptions with rule_id 0 and verified crawlers skip it, so search engines keep indexing; a request that only claims to be a crawler is challenged. hosts limits it to some names of the zone. Set until and the control plane switches it off at that time as a new zone version, recorded in the history and the audit log.
Turn it on from the zone overview or Security → Verification (1 h, 6 h, 24 h or until you turn it off), with openwaf-cloud ctl zones under-attack example.com on --for 6h --reason "…", with challenge.under_attack in PATCH /v1/orgs/{org}/zones/{zone}/edge, or with the new MCP tool under_attack. Its challenges appear under the under_attack trigger in the Verification analytics.
Under attack mode asks for a click
On a fast connection the proof of work of under attack mode finished before visitors noticed it, and a script that could compute SHA-256 passed just the same. The challenge page now adds an interactive step: once the proof of work is solved, it shows an «I am human» button («Soy humano» in Spanish), focused and announced to screen readers, with the zone's brand and accent colour. Only a trusted browser input event counts (a click, tap, or Enter or Space): a click synthesised by a page script, such as element.click(), fails, and a click that comes too soon is rejected with interaction-required, which stops instant replays. Browsers that report they are automated get the same button, with no extra fingerprinting. Passes, their lifetime and scope don't change.
The step is friction for scripts, not proof of a human: automation that injects input through the browser or the operating system (Playwright or Puppeteer over the DevTools protocol, for example) produces trusted events and can pass. It makes each new pass cost a real interaction.
It is on by default. Set challenge.under_attack.interactive to false for the proof of work alone: Ask for a click (I am human) in the under attack card of the dashboard, "interactive": false in PATCH /v1/orgs/{org}/zones/{zone}/edge, openwaf-cloud ctl zones under-attack example.com on --interactive=false, or interactive in the MCP tool under_attack. Solves with the click are counted as interactive in the Verification analytics.