# Security model

CAPTCHA is an anti-automation signal, not authentication or authorization. Continue using CSRF protection, rate limiting, validation, secure sessions, and access control.

## Enforced by the self-hosted engine

- Answers are stored as HMAC-SHA-256 digests with a per-challenge salt.
- Challenge IDs and response tokens use cryptographically secure random bytes.
- Challenges expire, have attempt limits, and are consumed after a correct answer.
- Response tokens are opaque, hashed at rest, action-bound, and single-use by default.
- Optional `captchaGuard({ verifiedForMs })` grants are session-bound, action-bound, and short-lived; use them only for retryable operations and retain independent rate limits.
- Optional hostname, session, and IP bindings are validated with constant-time comparisons.
- Audio URLs contain a random access key and are private/no-store.
- Public challenge payloads never include the answer. Renderer names and disturbance metadata are safe to expose because they do not reveal the answer.
- Same-origin HTTP handlers and independent create/verify rate limits are enabled by default.
- The `not-robot` checkbox uses timing, honeypot, expiry, attempt limits, bindings, and one-use verification; it is intentionally low-friction and should escalate to a stronger challenge when risk is high.

## Required deployment controls

1. Set `CAPTCHA_SECRET` to at least 32 unpredictable characters and rotate it through your secret manager.
2. Use Redis, SQL, or another shared atomic store in multi-instance production deployments.
3. Always verify the response token on the server. Never trust only a client event or hidden input.
4. Bind every CAPTCHA to a stable action such as `signup`, `login`, or `contact-submit`.
5. Restrict managed and third-party keys to expected hostnames.
6. Never pass a secret key to `<Captcha />` or serialize it into browser output.
7. Apply route-level rate limits before expensive image/audio generation.
8. Use TLS in production and avoid logging answers, raw tokens, secret keys, or unnecessary raw IP addresses.
9. Offer an accessible alternative to visual challenges. Hard renderers and disturbance near 75 should never be the only available path.
10. Prefer `imageStyle="random"` or a controlled pool to reduce static segmentation patterns, but do not treat renderer randomness as a replacement for server verification, expiry, attempt limits, or rate limiting.
11. Keep provider SDK behavior and verification rules current before release.

## Reporting

Report suspected vulnerabilities privately to the WorkRoot/WRNexusJS maintainers. Do not open a public issue containing active keys, tokens, or exploit details.
