CAPTCHA
Overview
The CAPTCHA system supports three providers, selectable globally. Challenge actions are available for WAF rules, Security Rules, and rate limits. When a challenge is triggered, the client is redirected to a challenge page, and upon successful completion, a cookie is issued that bypasses future challenges for a configurable TTL.
Providers
Native (cap)
The built-in proof-of-work service. This is the default provider and requires no external service or API keys. The challenge is self-hosted and served by coreX Manager.
reCAPTCHA
Google reCAPTCHA v2 or v3 (with configurable score threshold). Requires a site key and secret from Google.
Turnstile
A CAPTCHA widget from an external provider. Requires a site key and secret.
reCAPTCHA is a Google service and Turnstile is a service from another company. Both require their own site keys and secrets. The Native provider is self-hosted by coreX Manager and requires no external service.
Challenge Action
The challenge action is available for:
- WAF rules — challenge requests that exceed the anomaly threshold
- Security Rules — challenge requests matching a rule expression
- Rate limits — challenge clients that exceed the rate limit
When triggered, the challenge action:
- Checks for a valid
_cvcookie - If valid, allows the request through
- If invalid, emits a redirect to the challenge page with rule context
- The challenge page presents the CAPTCHA
- On success, sets the
_cvcookie and redirects back to the original URL
Client Binding
The _cv token is bound to the client via a hash of:
- Client IP
- User-Agent
- JA4 TLS fingerprint
This means a leaked cookie cannot be replayed from a different client.
Binding to the JA4 fingerprint adds another layer of client identity beyond IP and User-Agent. Even if an attacker steals the cookie and spoofs the IP and User-Agent, a different TLS client will have a different JA4 fingerprint and fail the binding check.
Request ID
HAProxy’s unique-id is passed through the challenge pipeline for correlation with access logs and WAF metrics. This lets you trace a challenge event back to the original request.
Global TTL
captcha_valid_seconds (default 3600 = 1 hour) controls how long the _cv cookie is valid. Configurable from the CAPTCHA page UI.
Challenge Event Tracking
The system logs three event types per rule:
- Issued — a challenge was presented
- Solved — the challenge was completed successfully
- Failed — the challenge was attempted but failed
Each event includes the request_id for correlation.
Settings Page
The CAPTCHA settings page has three tabs:
Provider Tab
- Provider selector (Native / reCAPTCHA / Turnstile)
- Per-provider configuration fields:
- Native: no configuration needed
- reCAPTCHA: site key, secret, version (v2/v3), score threshold (v3)
- Turnstile: site key, secret
Stats Tab
- Per-rule solve rate
- Recent challenge events (issued, solved, failed)
Keys Tab (Native provider only)
- Cap admin API proxy for managing Native provider keys
Step-by-Step: Configure the Native Provider
- Navigate to Security > CAPTCHA
- In the Provider tab, select Native
- Set the TTL (default 3600 is fine)
- Click Save
- No keys or external configuration needed — the Native provider is ready to use
Step-by-Step: Configure reCAPTCHA
- Obtain a site key and secret from Google reCAPTCHA
- Navigate to Security > CAPTCHA
- Select reCAPTCHA as the provider
- Enter the site key and secret
- Select version (v2 or v3)
- If v3, set the score threshold (e.g. 0.5)
- Click Save
Step-by-Step: Create a Challenge Rule
-
Navigate to Security > Security Rules
-
Click Add Rule
-
Name:
challenge-suspicious -
Expression:
risk.score > 50 -
Action: challenge
-
Save and Apply
-
Test:
curl -k https://localhost/A request that triggers the rule should redirect to the challenge page.
Verification
-
Trigger a challenge:
curl -k -v https://localhost/ 2>&1 | grep -i 'location\|set-cookie'Expect a redirect to the challenge page and no
_cvcookie on the first request. -
Complete the challenge and verify the
_cvcookie is set. -
Re-request with the cookie:
curl -k -b "_cv=<token>" https://localhost/The request should pass through without a challenge.
-
Check stats:
- Navigate to Security > CAPTCHA > Stats
- Verify issued, solved, and failed events appear
Next Steps
- Security Rules — Create rules that trigger challenges
- WAF — Use challenge actions in WAF rules
- Rate Limiting — Challenge clients that exceed limits