fix: exempt loopback from TierAuth so local vault run doesn't get 429'd #97
+10
−8
Claude / Claude Code Review
completed
Apr 21, 2026 in 11m 4s
Code review found 2 important issues
Found 5 candidates, confirmed 3. See review comments for details.
Details
| Severity | Count |
|---|---|
| 🔴 Important | 2 |
| 🟡 Nit | 0 |
| 🟣 Pre-existing | 0 |
| Severity | File:Line | Issue |
|---|---|---|
| 🔴 Important | internal/server/server.go:847-849 |
ipKeyer loopback exemption removes rate limiting from register, forgot-password, and resend-verification |
| 🔴 Important | internal/ratelimit/key.go:29-37 |
IPKeySkipLoopback uses XFF-derived IP, enabling loopback spoofing to bypass all ipAuth limits when AGENT_VAULT_TRUSTED_P |
Annotations
Check failure on line 849 in internal/server/server.go
claude / Claude Code Review
ipKeyer loopback exemption removes rate limiting from register, forgot-password, and resend-verification
The PR's loopback exemption in `ipKeyer()` (server.go:847-849) is overly broad: it bypasses TierAuth for ALL routes using `ipAuth`, not just the four static reads that motivated the change. The PR description claims 'Login/register still enforce their own in-handler buckets directly on the raw IP,' but this is only true for `handleLogin` (handle_auth.go:594-596); `handleRegister`, `handleForgotPassword`, `handleResendVerification`, `handleResetPassword`, and `handleVerify` have NO in-handler IP
Check failure on line 37 in internal/ratelimit/key.go
claude / Claude Code Review
IPKeySkipLoopback uses XFF-derived IP, enabling loopback spoofing to bypass all ipAuth limits when AGENT_VAULT_TRUSTED_PROXIES is set
The new IPKeySkipLoopback function checks the XFF-derived clientIP() result for loopback rather than the actual TCP connection address (r.RemoteAddr); when AGENT_VAULT_TRUSTED_PROXIES is set and the proxy is misconfigured to forward client-supplied XFF verbatim (nginx proxy_set_header X-Forwarded-For $http_x_forwarded_for), an attacker can send X-Forwarded-For: 127.0.0.1 and clientIP() returns 127.0.0.1, causing IPKeySkipLoopback to return "" and the rate-limit middleware to fail open. The fix i
Loading