# Verify blocks lying browsers, off by default

> A new risk scoring rule refuses challenges from scripts whose TLS handshake and client hints both contradict the browser they claim to be. Off by default; log or enforce per zone.

[Risk scoring](https://developers.openwaf.dev/waf/verify-risk/) has a new zone setting, `challenge.risk.lie_block`: [lying browsers](https://developers.openwaf.dev/waf/verify-risk/#lie-block). It catches a challenge when two independent checks on the server both say the client lies about its browser: the TLS ClientHello doesn't match the browser in the User-Agent (`tls_mismatch`), the `Sec-CH-UA` client hints contradict it too (`client_hints_mismatch`), and the handshake comes from no browser's TLS stack at all.

Each check alone can come from a real person: a corporate proxy that inspects TLS, a User-Agent switcher, DevTools device emulation. That's why neither blocks on its own, and why the rule only fires when the TLS stack isn't a browser's. Firefox, Safari, Android WebViews and browsers on iOS are never asked for client hints.

It works on the challenge page and the [Verify widget](https://developers.openwaf.dev/waf/verify-widget/), when the challenge is issued and when it is solved. It is **off** by default. In `log` it only counts; in `enforce` it answers `403`, the same as the score's `block` level, whatever the score and even with the block threshold at `0`. It needs risk scoring in `log` or `enforce`.

Turn it on in **Security → Verification → Risk scoring → Block lying browsers**, with `PATCH …/edge` and `{"challenge": {"risk": {"lie_block": "log"}}}`, `openwaf-cloud ctl zones set example.com challenge.risk.lie_block=log` or the MCP tool `update_settings`. The Verification analytics (dashboard, `openwaf-cloud ctl challenge report`, MCP `challenge_report`) show `risk.lie_block` and `risk.browser_lie`, the challenges the rule caught; `risk.blocked` includes them in `enforce`. Start in `log` and switch to `enforce` once you've seen a few days of normal traffic.
