Security: X-Forwarded-For trust enables complete rate-limit bypass #72

Open
opened 2026-05-11 13:48:48 +00:00 by thabeta · 0 comments
Owner

Severity: Critical

Location

crates/hero_aibroker_lib/src/middleware/ratelimit.rsextract_client_ip()

Finding

The rate limiter extracts client IP from X-Forwarded-For header with no trusted proxy validation:

fn extract_client_ip(request: &Request) -> Option<IpAddr> {
    if let Some(forwarded) = request.headers().get("x-forwarded-for")
        && let Ok(value) = forwarded.to_str()
        && let Some(ip_str) = value.split(',').next()
        && let Ok(ip) = ip_str.trim().parse()
    {
        return Some(ip);
    }
    // ...
    None
}

Attack Scenario

  • Any client can spoof their IP by sending arbitrary X-Forwarded-For headers
  • Rate limiting is completely bypassable
  • Billing and usage attribution based on IP are meaningless
  • Attackers can rotate IPs trivially to avoid all rate limits

Recommendation

  • Only trust X-Forwarded-For when behind a known reverse proxy
  • Use axum::extract::ConnectInfo for direct connection IP
  • Maintain a trusted proxy CIDR list
  • Default to connection peer address, not headers
## Severity: Critical ## Location `crates/hero_aibroker_lib/src/middleware/ratelimit.rs` — `extract_client_ip()` ## Finding The rate limiter extracts client IP from `X-Forwarded-For` header with no trusted proxy validation: ```rust fn extract_client_ip(request: &Request) -> Option<IpAddr> { if let Some(forwarded) = request.headers().get("x-forwarded-for") && let Ok(value) = forwarded.to_str() && let Some(ip_str) = value.split(',').next() && let Ok(ip) = ip_str.trim().parse() { return Some(ip); } // ... None } ``` ## Attack Scenario - Any client can spoof their IP by sending arbitrary `X-Forwarded-For` headers - Rate limiting is completely bypassable - Billing and usage attribution based on IP are meaningless - Attackers can rotate IPs trivially to avoid all rate limits ## Recommendation - Only trust `X-Forwarded-For` when behind a known reverse proxy - Use `axum::extract::ConnectInfo` for direct connection IP - Maintain a trusted proxy CIDR list - Default to connection peer address, not headers
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
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
lhumina_code/hero_aibroker#72
No description provided.