fix(ci): satisfy clippy filter_next in rate-limit XFF parsing#90
Conversation
When HTTP_TRUSTED_PROXIES is configured, use X-Real-IP or the rightmost X-Forwarded-For hop instead of the client-controlled leftmost entry. This closes a rate-limit bypass and DoS amplification path behind nginx-style reverse proxies that append the connecting address. Co-authored-by: Alexander Wagner <info@alexanderwagnerdev.com>
Replace filter().next_back() with rfind() when selecting the rightmost non-empty X-Forwarded-For hop, as required by clippy::filter_next. Co-authored-by: Alexander Wagner <info@alexanderwagnerdev.com>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_3fe1a495-96ed-408f-8496-3e85378834f8) |
|
@codex review |
PR Summary by QodoFix clippy filter_next and harden trusted-proxy client IP parsing
AI Description
Diagram
High-Level Assessment
Files changed (3)
|
Code Review by Qodo
Context used✅ Compliance rules (platform):
5 rules✅ Cross-repo context Not relevant to this PR:
OpenRTMP/librtmp2 Not relevant to this PR:
OpenRTMP/librtmp2-server-panel Not relevant to this PR:
AlexanderWagnerDev/nginx-obs-automatic-low-bitrate-switching 1.
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d193a047bc
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if let Some(real_ip) = request | ||
| .headers() | ||
| .get("X-Real-IP") | ||
| .and_then(|v| v.to_str().ok()) | ||
| .map(str::trim) | ||
| .filter(|part| !part.is_empty()) | ||
| .and_then(|part| part.parse::<IpAddr>().ok()) |
There was a problem hiding this comment.
Do not trust a pass-through X-Real-IP header
When an existing trusted-proxy setup safely appends or overwrites X-Forwarded-For but passes X-Real-IP through unchanged, a client can now supply an arbitrary valid X-Real-IP. Because this new branch takes precedence over the proxy-sanitized XFF value, the client can select a fresh rate-limit bucket for every request and evade per-IP limits. The previous documented contract only required trusted proxies to set XFF, so either avoid consuming this header or require a separately configured guarantee that the proxy overwrites it.
Useful? React with 👍 / 👎.
| if let Some(client) = xff | ||
| .split(',') | ||
| .map(str::trim) | ||
| .rfind(|part| !part.is_empty()) | ||
| .and_then(|part| part.parse::<IpAddr>().ok()) |
There was a problem hiding this comment.
Skip trusted hops when resolving an XFF chain
When traffic crosses more than one trusted proxy, selecting the rightmost XFF entry identifies the proxy immediately upstream of the TCP peer, not the originating client. For example, client -> proxy A -> proxy B -> server produces client, proxy A at the server, so every client routed through proxy A shares one bucket and can collectively exhaust the API or stats limit. Since the configuration can contain all trusted proxy addresses, resolve from right to left while skipping trusted hops and use the first untrusted address instead.
Useful? React with 👍 / 👎.
When a trusted proxy's X-Real-IP or X-Forwarded-For value is present but not a valid IpAddr, client_ip() silently fell back to the proxy's own peer IP, collapsing many clients into one rate-limit bucket with no operator-visible signal. Log a warning in that case instead.
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_7b10e5db-c272-4cd9-8b18-b1615bbac8d2) |
A trusted reverse proxy is only guaranteed to append to X-Forwarded-For ($proxy_add_x_forwarded_for); X-Real-IP is commonly passed through unmodified by proxies that don't set it themselves. Trusting it let a client pick an arbitrary rate-limit bucket by sending the header directly, reopening the bypass this PR is meant to close. Also fixes cargo fmt formatting on the rightmost-XFF match arm.
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_66b0b2ed-82ed-4afe-9ae5-d9a6562ce9fa) |
|
Addressed the review feedback:
CI/fmt/clippy all green on the latest commit. Generated by Claude Code |
|
Code review by qodo was updated up to the latest commit c0c4d97 |
Summary
Fixes the
cargo build & testCI failure on PR #89 caused byclippy::filter_next(-D warnings).Changes
.filter(|part| !part.is_empty()).next_back()with.rfind(|part| !part.is_empty())when selecting the rightmost non-emptyX-Forwarded-Forhop inclient_ip().Context
Broken by: #89
Failure: https://github.com/OpenRTMP/librtmp2-server/actions/runs/29549064766/job/87787531321
Need help on this PR? Tag
/codesmithwith what you need. Autofix is disabled.Note
Medium Risk
Changes how client IPs are derived for HTTP rate limits behind proxies, which can shift throttling behavior in production; the change is intentional hardening against header spoofing.
Overview
HTTP rate limiting behind trusted proxies no longer keys buckets off the leftmost
X-Forwarded-Forentry (client-spoofable). For trusted peers,client_ip()now takes the rightmost non-empty hop—the address the immediate proxy appended—and does not useX-Real-IP.Unparsable rightmost hops log a warning and fall back to the TCP peer IP. Config docs for
http_trusted_proxiesmatch this behavior. XFF parsing uses.rfind()instead of.filter().next_back()for clippy::filter_next CI. Tests cover rightmost selection, ignoring spoofed leftmost XFF, and ignoringX-Real-IP. Cargo.lock bumpstokio/tokio-macrospatch versions.Reviewed by Cursor Bugbot for commit c0c4d97. Bugbot is set up for automated code reviews on this repo. Configure here.