Skip to content

Captcha hardening: shared secret, 499 to 403, metrics polish#3

Merged
sergeyfast merged 3 commits into
masterfrom
captcha-hardening
May 2, 2026
Merged

Captcha hardening: shared secret, 499 to 403, metrics polish#3
sergeyfast merged 3 commits into
masterfrom
captcha-hardening

Conversation

@sergeyfast
Copy link
Copy Markdown
Contributor

Summary

  • Require Captcha.Secret (>= 32 bytes) when Captcha.Provider is set; fixes forgeable waf_pass cookies caused by the hardcoded default. Warn at startup when memory storage is used with multiple instances.
  • Migrate captcha status code from 499 to 403 (nginx 499 conflicts with client-disconnect semantics) and introduce X-WAF-Action: captcha|block|throttle so clients can disambiguate. Add Decision.BlockRetryAfter / RateLimit.RetryAfter (60s default).
  • Polish adaptive-captcha-expansion metrics: add wafsrv_attack_mode_active gauge, rename attack_score_boost_applied_totalattack_score_boost_total, sharpen Help texts; proxy no_backends recorder uses target="-" so Grafana renders it.

Test plan

  • make fmt lint is clean
  • go test ./... passes (unit + decide + ip + limit + config)
  • e2e: go test ./e2e -run TestCaptcha (captcha 403 + X-WAF-Action, escalation to soft block, throttle, composite-key isolation)
  • Startup with Captcha.Provider set but no/short Captcha.Secret fails fast
  • Dashboard config tab and builder import/export show Captcha.Secret
  • Prometheus exposes wafsrv_attack_mode_active and wafsrv_attack_score_boost_total

sergeyfast added 3 commits May 2, 2026 16:34
- Add wafsrv_attack_mode_active gauge for operator queries
- Rename attack_score_boost_applied_total to attack_score_boost_total
- Clarify attack_only_match_total help (strict subset of traffic_filter)
- Clarify attack_score_boost_total help: threshold crossings only
- Use target="-" in proxy no_backends recorder so Grafana renders it
- Switch Decision.CaptchaStatusCode default from 499 to 403
- Add X-WAF-Action header (captcha|block|throttle) to disambiguate
- Set rc.Decision in ip and limit middlewares for access-log
- Add Decision.BlockRetryAfter and RateLimit.RetryAfter (60s default)
- Emit Retry-After on block, soft block, blacklist, and 429
- Refactor isSoftBlocked and isBlacklisted to return remaining TTL
- Update tests for X-WAF-Action and Retry-After semantics
- Require Captcha.Secret >= 32 bytes when Captcha.Provider is set
- Fix forgeable waf_pass cookies caused by hardcoded default secret
- Warn at startup when Captcha.Provider uses memory storage
- Surface Secret in cfg/local.toml.dist, dashboard, builder import
- Add config_test cases: missing, short, valid, disabled
- Add e2e captcha tests covering the 499 to 403 migration
@sergeyfast sergeyfast merged commit 8c22e50 into master May 2, 2026
2 checks passed
@sergeyfast sergeyfast deleted the captcha-hardening branch May 2, 2026 13:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant