Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🐹
🐹 Go
Not in CISA KEV
MEDIUM severity

Fabio - Incomplete fix for CVE-2025-48865: operator-configured trust headers (clientip/tls/requestid) still strippable via the Connection headerGHSA-fq95-v8xc-jm3v

MEDIUMFix: fabiolb/fabio@240526a

GHSA-fq95-v8xc-jm3v is a medium-severity (CVSS 5.8) CWE-290 vulnerability in github.com/fabiolb/fabio. A fix is available for github.com/fabiolb/fabio — see the affected versions and patch details below.

Also known asCVE-2026-62987GO-2026-6566
Published
Updated
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Oct 23, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
  • CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.

Exploitation and automatability from CISA’s SSVC triage for GHSA-fq95-v8xc-jm3v.

EPSS Exploitation Probability

via FIRST.org ↗
0.2%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs10th percentile — riskier than 10% of all scored CVEsHighest risk
0.00%0.23%0.47%0.70%0.2%0.2%Oct 26Oct 26

Probability of exploitation in the next 30 days, from FIRST.org EPSS.

How urgent is this, really

GHSA-fq95-v8xc-jm3v by exploitation likelihood (EPSS) against impact (CVSS). Outside the shaded patch-first corner.

Where this sits among everything scored

Of 394,803 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Counts from FIRST.org, log-scaled.

Real-World Exposure

1 pkg affected
🐹github.com/fabiolb/fabio

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects Go packages — download data is not available via public APIs for these ecosystems.

Description

Affected: github.com/fabiolb/fabio >= 1.6.6 through 1.7.1 and master HEAD (c75f8a6).

Summary

The v1.6.6 fix for CVE-2025-48865 sweeps the client Connection header against a hardcoded allowlist protectHeaders (proxy/http_headers.go:28-36) containing only the 7 X-Forwarded family headers. Fabio also injects three operator-configured server-side trust headers that are NOT in that allowlist, so the original hop-by-hop stripping attack still works against them.

Details

The three unprotected trust headers and where fabio sets them:

  • ClientIPHeader (proxy.header.clientip) - http_headers.go:73 r.Header.Set(cfg.ClientIPHeader, remoteIP)
  • TLSHeader (proxy.header.tls) - http_headers.go:153 r.Header.Set(cfg.TLSHeader, cfg.TLSHeaderValue) (TLS connections)
  • RequestID (proxy.header.requestid) - http_proxy.go:90 r.Header.Set(p.Config.RequestID, id())

Order of operations in HTTPProxy.ServeHTTP: (1) line 90 sets RequestID; (2) line 175 calls addHeaders, which sweeps the Connection header (keeping the three configured names because they are absent from protectHeaders) and then sets ClientIPHeader/TLSHeader; (3) line 223 runs the Go httputil.ReverseProxy, whose removeHopByHopHeaders (Go stdlib net/http/httputil/reverseproxy.go) iterates the inbound Connection header and h.Dels every listed header. The three trust headers fabio just set are therefore deleted before the request reaches the backend.

PoC

Configure proxy.header.clientip=X-Client-IP, proxy.header.requestid=X-Request-ID. Raw request:

GET / HTTP/1.1
Host: foo.com
Connection: close, X-Client-IP, X-Request-ID

Backend sees X-Client-IP: <empty> and X-Request-ID: <empty>. Baseline (Connection: close) => backend sees the real client IP and a request id. The same works for proxy.header.tls over TLS (Connection: close, X-Secure strips the TLS assertion). Reproduced by the two PASS-ing tests in proxy/poc_cve48865_incomplete_test.go on master HEAD (Go 1.26.4). Control: X-Forwarded-For (in protectHeaders) survives, confirming the gap is specific to the configured headers.

Impact

Where a backend trusts these fabio-set headers, an external unauthenticated client can strip/downgrade the trust signal: bypass/poison IP-based ACL or audit that reads the clientip header, downgrade a TLS-terminated request to appear non-TLS to a backend keying off the TLS header, or drop request-id correlation. Scope: deployments that enable the relevant proxy.header.* option (all empty by default). Fix: add the configured ClientIPHeader/TLSHeader/RequestID names to the protectHeaders set (or strip their token from the inbound Connection header) inside addHeaders.

Parent: CVE-2025-48865 / GHSA-q7p4-7xjv-j3wf (fixed in v1.6.6). This is an incomplete-fix sibling - the same hop-by-hop stripping primitive applies to the operator-configured trust headers the allowlist does not cover.

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐹Gogithub.com/fabiolb/fabio≥ 1.6.6&&< 1.7.21.7.2go get github.com/fabiolb/fabio@v1.7.2

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for github.com/fabiolb/fabio, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update github.com/fabiolb/fabio to 1.7.2 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-fq95-v8xc-jm3v is resolved across your whole dependency graph.

  3. Workarounds

    If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.

Frequently Asked Questions

**Affected:** github.com/fabiolb/fabio >= 1.6.6 through 1.7.1 and master HEAD (c75f8a6). ### Summary The v1.6.6 fix for CVE-2025-48865 sweeps the client `Connection` header against a hardcoded allowlist `protectHeaders` (proxy/http_headers.go:28-36) containing only the 7 X-Forwarded family headers. Fabio also injects three *operator-configured* server-side trust headers that are NOT in that allowlist, so the original hop-by-hop stripping attack still works against them. ### Details The three unprotected trust headers and where fabio sets them: - ClientIPHeader (`proxy.header.clientip`) - htt
O3 Security · Impact-Aware SCA

Is GHSA-fq95-v8xc-jm3v in your dependencies?

Find it across Go, including transitive dependencies.

Fabio - Incomplete fix for CVE-2025-48865: operator-config…