fix: only trust proxy headers from RFC1918/loopback sources (closes #44) #47

Merged
sneak merged 1 commits from :fix/realip-trusted-proxy into main 2026-02-16 07:03:23 +01:00
Collaborator

Summary

Fixes the security issue where realIP() unconditionally trusts X-Real-IP and X-Forwarded-For headers from any client, allowing attackers to bypass the login rate limiter by spoofing headers.

Changes

  • realIP() now parses RemoteAddr and only trusts proxy headers when the source IP is RFC1918 (10/8, 172.16/12, 192.168/16), loopback (127/8), or IPv6 ULA/loopback
  • Public source IPs have headers ignored — fail closed, uses RemoteAddr
  • Added isTrustedProxy() helper with pre-parsed CIDR nets
  • Updated tests to cover both trusted proxy (headers honoured) and untrusted proxy (headers ignored) scenarios
  • Added TestIsTrustedProxy unit test

(closes #44)

## Summary Fixes the security issue where `realIP()` unconditionally trusts `X-Real-IP` and `X-Forwarded-For` headers from any client, allowing attackers to bypass the login rate limiter by spoofing headers. ## Changes - `realIP()` now parses `RemoteAddr` and only trusts proxy headers when the source IP is RFC1918 (10/8, 172.16/12, 192.168/16), loopback (127/8), or IPv6 ULA/loopback - Public source IPs have headers ignored — fail closed, uses `RemoteAddr` - Added `isTrustedProxy()` helper with pre-parsed CIDR nets - Updated tests to cover both trusted proxy (headers honoured) and untrusted proxy (headers ignored) scenarios - Added `TestIsTrustedProxy` unit test (closes #44)
sneak was assigned by clawbot 2026-02-16 07:02:14 +01:00
clawbot added 1 commit 2026-02-16 07:02:15 +01:00
realIP() now parses RemoteAddr and checks if the source IP is in
RFC1918 (10/8, 172.16/12, 192.168/16), loopback (127/8), or IPv6
ULA/loopback ranges before trusting X-Real-IP or X-Forwarded-For
headers. Public source IPs have headers ignored (fail closed).

This prevents attackers from spoofing X-Forwarded-For to bypass
the login rate limiter.
Author
Collaborator

CI Results

Tests (make test)

All packages pass.

Lint (golangci-lint run ./...)

No new issues. One pre-existing testpackage lint warning in internal/handlers/tail_validation_test.go (unrelated to this PR).

## CI Results ### Tests (`make test`) ✅ All packages pass. ### Lint (`golangci-lint run ./...`) ✅ No new issues. One pre-existing `testpackage` lint warning in `internal/handlers/tail_validation_test.go` (unrelated to this PR).
sneak merged commit c4c62c9aba into main 2026-02-16 07:03:23 +01:00
Sign in to join this conversation.
No reviewers
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: sneak/upaas#47
No description provided.