Skip to content

fix: use last IP from X-Forwarded-For to prevent rate limit bypass#1033

Open
RyoSXu wants to merge 1 commit into
glanceapp:mainfrom
RyoSXu:fix/x-forwarded-for-spoofing
Open

fix: use last IP from X-Forwarded-For to prevent rate limit bypass#1033
RyoSXu wants to merge 1 commit into
glanceapp:mainfrom
RyoSXu:fix/x-forwarded-for-spoofing

Conversation

@RyoSXu

@RyoSXu RyoSXu commented Jul 2, 2026

Copy link
Copy Markdown

Summary

When the server is configured with proxied: true, addressOfRequest() was returning the first (leftmost) IP from the X-Forwarded-For header. This value is client-controlled and can be spoofed, allowing attackers to bypass the login rate limit by rotating the spoofed IP on each request.

The fix changes the function to use the last (rightmost) IP instead, which is the one appended by the trusted reverse proxy (e.g., nginx with $proxy_add_x_forwarded_for). This ensures the rate limiter always sees the real client IP address.

Changes

  • internal/glance/glance.go: Modified addressOfRequest() to return the last IP in X-Forwarded-For with strings.TrimSpace() to handle whitespace
  • internal/glance/address_test.go (new): 8 test cases covering:
    • Non-proxied mode (uses RemoteAddr)
    • Proxied mode with no XFF header (falls back to RemoteAddr)
    • Single IP in XFF
    • Multiple IPs in XFF (returns last)
    • Spoofed first IP (ignored, returns real IP from the end)
    • Empty XFF (falls back to RemoteAddr)
    • Trailing comma (falls back to RemoteAddr)
    • Whitespace trimming

Testing

  • All 9 tests pass (8 new + 1 existing TestAuthTokenGenerationAndVerification)
  • go test ./internal/glance/ -v passes

Fixes #1031

When the server is configured with proxied: true, addressOfRequest()
was returning the first (leftmost) IP from the X-Forwarded-For header.
This value is client-controlled and can be spoofed, allowing attackers
to bypass the login rate limit by rotating the spoofed IP on each
request.

The fix changes the function to use the last (rightmost) IP instead,
which is the one appended by the trusted reverse proxy. This ensures
the rate limiter always sees the real client IP address.

Changes:
- Modified addressOfRequest() to return the last IP in X-Forwarded-For
  with strings.TrimSpace() to handle whitespace
- Added 8 test cases covering: non-proxied mode, missing XFF header,
  single IP, multiple IPs, spoofed first IP, empty XFF, trailing
  comma fallback, and whitespace trimming

Fixes glanceapp#1031
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.

Authentication Rate Limit Bypass via X-Forwarded-For Spoofing

1 participant