🐛 fix(proxy): backport BalancerForward X-Real-IP overwrite fix to v2 - #4495
ReneWerner87 merged 3 commits into
Conversation
Backport of the v3 fix (1403cc8, PR gofiber#4260) for GHSA-gcfq-8gqf-4876 / CVE-2026-45045 to the v2 branch: Header.Add kept an attacker-supplied X-Real-IP as the first header value, so upstream servers reading the first value trusted the spoofed IP. Header.Set overwrites it with the real client IP (c.IP()). Adds the corresponding regression test adapted to v2's *fiber.Ctx handler signature, and fixes the same insecure pattern in the proxy middleware doc example.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
Walkthrough
ChangesX-Real-IP Overwrite Behavior
Estimated code review effort: 1 (Trivial) | ~5 minutes Possibly related PRs
Suggested labels: Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 golangci-lint (2.12.2)level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies" Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@ReneWerner87 I dont think the CI for v2 works anymore. |
|
ok, let me fix this |
|
Related #4219 |
|
Congrats on merging your first pull request! 🎉 We here at Fiber are proud of you! If you need help or want to chat with us, join us on Discord https://gofiber.io/discord |
|
Hi maintainers, Thanks for merging this backport. I have a question: is there a planned release tag for As of today, the latest v2 release is Why this matters for v2 consumers:
Would it be possible to cut a Thank you! |
Dependabot flagged CVE-worthy behavior in gofiber's BalancerForward proxy helper: it used Header.Add() instead of Header.Set() when injecting X-Real-IP, letting an attacker-supplied value survive alongside the real client IP. padduck doesn't import gofiber/fiber/v2/middleware/proxy (only logger and recover are vendored), so this was never reachable here, but bumping to the patched release (which backports gofiber/fiber#4495) is cheap and closes the Dependabot alert. Also carries the govulncheck Makefile fix from the unmerged fix/database-url-userinfo-encoding branch (checks Go version from backend/ instead of the repo root, which has no go.mod) — needed here too since this branch was cut from main before that PR merged. Claude-Session: https://claude.ai/code/session_01W5iuFK1sBPceJfvaYnjAot
Dependabot flagged CVE-worthy behavior in gofiber's BalancerForward proxy helper: it used Header.Add() instead of Header.Set() when injecting X-Real-IP, letting an attacker-supplied value survive alongside the real client IP. padduck doesn't import gofiber/fiber/v2/middleware/proxy (only logger and recover are vendored), so this was never reachable here, but bumping to the patched release (which backports gofiber/fiber#4495) is cheap and closes the Dependabot alert. Also carries the govulncheck Makefile fix from the unmerged fix/database-url-userinfo-encoding branch (checks Go version from backend/ instead of the repo root, which has no go.mod) — needed here too since this branch was cut from main before that PR merged. Claude-Session: https://claude.ai/code/session_01W5iuFK1sBPceJfvaYnjAot
Summary
Backports the
v3fix for GHSA-gcfq-8gqf-4876 / CVE-2026-45045 ("GoFiberVulnerable to X-Real-IP Spoofing via Header.Add() in BalancerForward") to the
v2branch.BalancerForwardinmiddleware/proxy/proxy.gousesHeader.Add("X-Real-IP", c.IP())when forwarding a request to a backend. BecauseAddappends ratherthan replaces, a client-supplied
X-Real-IPheader is not removed — it iskept as the first value, with the real client IP appended as a second
value. Upstream servers that read only the first
X-Real-IPvalue (nginx,Express, and most HTTP servers) therefore trust the attacker-controlled value
for IP-based logging, rate limiting, ACLs, and geofencing, i.e. an
authentication/authorization-adjacent spoofing bypass (CWE-290).
The v3 branch was fixed in commit
1403cc8292da3220e9316960b4030cc722a0f396(PR #4260, "fix(proxy): Ensure BalancerForward overwrites X-Real-IP header"),
released in v3.3.0. Per the advisory, v2's
vulnerable_version_rangeis<= 2.52.13with no patched version published forgithub.com/gofiber/fiber/v2— the v2 branch never received this fix. This PR closes that gap.
Change
One-line fix in
middleware/proxy/proxy.go,BalancerForward: replaceHeader.AddwithHeader.Setso any attacker-suppliedX-Real-IPheader isoverwritten with the real client IP (
c.IP()) rather than retained alongsideit.
Also updates the matching code sample in
docs/api/middleware/proxy.md(thev2 equivalent of the doc fix in PR #4260), which showed the same insecure
Header.Addpattern, so the documented example doesn't teach the vulnerableusage.
Test
Added
Test_Proxy_Balancer_Forward_OverwritesXRealIPinmiddleware/proxy/proxy_test.go, adapted from the v3 regression test addedin PR #4260 (
Test_Proxy_Balancer_Forward_OverwritesXRealIP) to v2's*fiber.Ctxpointer-receiver handler signature and theutils.AssertEqualassertion helper used elsewhere in this file. The test sends a request
through
BalancerForwardwith a spoofedX-Real-IP: 10.0.0.1header alreadyset, and asserts the backend observes only the real (test-harness) client IP
and never the spoofed value.
Confirmed the test fails against the unpatched
Header.Addcall (backendobserves the spoofed
10.0.0.1as the first header value) and passes onceHeader.Setis restored.Compatibility
Behavior-only fix, no signature or config changes. Any caller currently
relying on the buggy "spoofed value plus real value" double header (there is
no legitimate reason to) would see only the real client IP going forward,
which is the documented and intended behavior.
References
Found via a Dependabot alert on a consuming project.