{"id":"CVE-2026-45045","title":"GoFiber Vulnerable to X-Real-IP Spoofing via Header.Add() in BalancerForward","summary":"GoFiber Vulnerable to X-Real-IP Spoofing via Header.Add() in BalancerForward","severity":"medium","cvss":5.3,"cwe":["CWE-290"],"vendor":"gofiber","product":"github.com/gofiber/fiber/v3","ecosystem":"go","affected":["github.com/gofiber/fiber/v3 <= 3.2.0","github.com/gofiber/fiber/v2 <= 2.52.13"],"patched":["github.com/gofiber/fiber/v3 3.3.0"],"published":"2026-07-02","updated":"2026-07-02","source":"GHSA","sourceUrl":"https://github.com/advisories/GHSA-gcfq-8gqf-4876","references":[{"url":"https://github.com/gofiber/fiber/security/advisories/GHSA-gcfq-8gqf-4876"},{"url":"https://github.com/advisories/GHSA-gcfq-8gqf-4876"}],"tags":["ghsa","go"],"ingestedAt":"2026-07-02T14:37:13.947Z","epss":0.00463,"epssPercentile":0.39361,"slug":"CVE-2026-45045","body":"## Overview\n\n## 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.\n\n## Affected packages\n\n- `github.com/gofiber/fiber/v3 <= 3.2.0`\n- `github.com/gofiber/fiber/v2 <= 2.52.13`\n\n## Remediation\n\nUpgrade to a patched release:\n\n- `github.com/gofiber/fiber/v3 3.3.0`","depth":"sunlit","depthScore":29,"depthScoreParts":{"impact":29.2,"likelihood":0.1,"exploitation":0,"ransomware":0},"changes":[]}