{"id":"GHSA-gcfq-8gqf-4876","revision":"c7ff7ea5e6604758b3ffeb0d44664ebd","records":[{"revision":"c7ff7ea5e6604758b3ffeb0d44664ebd","observedAt":"2026-10-24T13:19:41.952+00:00","statement":{"source":"osv","id":"GHSA-gcfq-8gqf-4876","aliases":["CVE-2026-45045","GO-2026-5887"],"title":"GoFiber Vulnerable to X-Real-IP Spoofing via Header.Add() in BalancerForward","description":"## Summary\n\nThe `BalancerForward` proxy helper in GoFiber uses `Header.Add()` instead of `Header.Set()` when injecting the `X-Real-IP` header. This appends the real client IP as a second header value rather than replacing any attacker-supplied value. Upstream servers that read the first `X-Real-IP` header (nginx, Express, most HTTP servers) use the attacker's spoofed IP for logging, rate limiting, and access control.\n\n## Vulnerable Code\n\n**File:** `middleware/proxy/proxy.go`, lines 270-285\n\n```go\nfunc BalancerForward(servers []string, clients ...*fasthttp.Client) fiber.Handler {\n    r := &roundrobin{\n        current: 0,\n        pool:    servers,\n    }\n    return func(c fiber.Ctx) error {\n        server := r.get()\n        if !strings.HasPrefix(server, \"http\") {\n            server = \"http://\" + server\n        }\n        c.Request().Header.Add(\"X-Real-IP\", c.IP())   // line 282: Add, not Set\n        return Do(c, server+c.OriginalURL(), clients...)\n    }\n}\n```\n\n## Data Flow\n\n1. Attacker sends request with `X-Real-IP: 10.0.0.1` (spoofed internal IP)\n2. `BalancerForward` handler executes at line 282\n3. `c.Request().Header.Add(\"X-Real-IP\", c.IP())` APPENDS the real IP as a second header\n4. Upstream server receives: `X-Real-IP: 10.0.0.1` AND `X-Real-IP: <real-attacker-ip>`\n5. Most HTTP servers (nginx, Node.js, Apache) read the FIRST value\n6. Upstream uses `10.0.0.1` for all IP-dependent logic\n\n## Impact\n\n- **Rate limit bypass:** IP-based rate limiting at the upstream uses the spoofed IP, allowing unlimited requests\n- **IP ACL bypass:** Internal IP allowlists (e.g., admin panels restricted to `10.0.0.0/8`) can be bypassed\n- **Audit log poisoning:** Security logs record the spoofed IP, making incident investigation unreliable\n- **Geolocation bypass:** IP-based geofencing or region restrictions are circumvented\n\n## Fix\n\nReplace `Header.Add()` with `Header.Set()` at line 282:\n\n```go\nc.Request().Header.Set(\"X-Real-IP\", c.IP())\n```\n\n`Header.Set()` replaces any existing header value, ensuring only the real client IP is forwarded.","state":0,"publishedAt":"2026-07-02T13:50:45+00:00","modifiedAt":"2026-09-10T03:50:52.0542005+00:00","affected":[{"ecosystem":"Go","name":"github.com/gofiber/fiber/v3","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0"},{"kind":"fixed","version":"3.3.0"}]}],"versions":[],"rawVersionEvidence":null},{"ecosystem":"Go","name":"github.com/gofiber/fiber/v2","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0"},{"kind":"fixed","version":"2.52.14"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[{"system":"CVSS_V3","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N","score":null,"severity":null},{"system":"Publisher rating","vector":null,"score":null,"severity":"MODERATE"}],"references":["https://github.com/gofiber/fiber/security/advisories/GHSA-gcfq-8gqf-4876","https://nvd.nist.gov/vuln/detail/CVE-2026-45045","https://github.com/gofiber/fiber/pull/4260","https://github.com/gofiber/fiber/pull/4495","https://github.com/gofiber/fiber/commit/1403cc8292da3220e9316960b4030cc722a0f396","https://github.com/gofiber/fiber/commit/33c9501288ab47a429c8b5e701493f0c3c0af37d","https://github.com/gofiber/fiber","https://github.com/gofiber/fiber/releases/tag/v2.52.14","https://github.com/gofiber/fiber/releases/tag/v3.3.0"],"sourceUrl":"https://github.com/advisories/GHSA-gcfq-8gqf-4876","license":"GitHub Advisory Database · CC-BY-4.0","key":"osv:GHSA-gcfq-8gqf-4876","identifiers":["GHSA-gcfq-8gqf-4876","CVE-2026-45045","GO-2026-5887"]},"retained":false,"historicalAffected":[]}],"coverage":[]}