Every CVE Search/ Get API key

CVE-2025-48865

Fabio allows HTTP clients to manipulate custom headers it adds

9.1 CriticalFix available

Fabio is an HTTP(S) and TCP router for deploying applications managed by consul. Prior to version 1.6.6, Fabio allows clients to remove X-Forwarded headers (except X-Forwarded-For) due to a vulnerability in how it processes hop-by-hop headers. Fabio adds HTTP headers like X-Forwarded-Host and X-Forwarded-Port when routing requests to backend applications. Since the receiving application should trust these headers, allowing HTTP clients to remove or modify them creates potential security vulnerabilities. Some of these custom headers can be removed and, in certain cases, manipulated. The attack relies on the behavior that headers can be defined as hop-by-hop via the HTTP Connection header. This issue has been patched in version 1.6.6.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
High
Integrity
High
Availability
None

Exploit likelihood

0.47%Up 0.5 points since May 30, 2025
90%50%10%1%

What each source reports

CVE List Score used 9.1

Fabio allows HTTP clients to manipulate custom headers it adds

Fabio is an HTTP(S) and TCP router for deploying applications managed by consul. Prior to version 1.6.6, Fabio allows clients to remove X-Forwarded headers (except X-Forwarded-For) due to a vulnerability in how it processes hop-by-hop headers. Fabio adds HTTP headers like X-Forwarded-Host and X-Forwarded-Port when routing requests to backend applications. Since the receiving application should trust these headers, allowing HTTP clients to remove or modify them creates potential security vulnerabilities. Some of these custom headers can be removed and, in certain cases, manipulated. The attack relies on the behavior that headers can be defined as hop-by-hop via the HTTP Connection header. This issue has been patched in version 1.6.6.

Record
CVE-2025-48865
CVSS 3.1
9.1 CriticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N
Weakness
CWE-345, CWE-348
Updated
2026-11-02
EUVDEUVD-2025-16398 9.1

Fabio is an HTTP(S) and TCP router for deploying applications managed by consul. Prior to version 1.6.6, Fabio allows clients to remove X-Forwarded headers (except X-Forwarded-For) due to a vulnerability in how it processes hop-by-hop headers. Fabio adds HTTP headers like X-Forwarded-Host and X-Forwarded-Port when routing requests to backend applications. Since the receiving application should trust these headers, allowing HTTP clients to remove or modify them creates potential security vulnerabilities. Some of these custom headers can be removed and, in certain cases, manipulated. The attack relies on the behavior that headers can be defined as hop-by-hop via the HTTP Connection header. This issue has been patched in version 1.6.6.

Record
EUVD-2025-16398
CVSS 3.1
9.1 CriticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-q7p4-7xjv-j3wf 9.1

Fabio allows HTTP clients to manipulate custom headers it adds

Summary

Fabio allows clients to remove X-Forwarded headers (except X-Forwarded-For) due to a vulnerability in how it processes hop-by-hop headers.

Fabio adds HTTP headers like X-Forwarded-Host and X-Forwarded-Port when routing requests to backend applications. Since the receiving application should trust these headers, allowing HTTP clients to remove or modify them creates potential security vulnerabilities.

However, it was found that some of these custom headers can indeed be removed and, in certain cases, manipulated. The attack relies on the behavior that headers can be defined as hop-by-hop via the HTTP Connection header. By setting the following connection header, the X-Forwarded-Host header can, for example, be removed:

Connection: close, X-Forwarded-Host

Similar critical vulnerabilities have been identified in other web servers and proxies, including CVE-2022-31813 in Apache HTTP Server and CVE-2024-45410 in Traefik.

Details

It was found that the following headers can be removed in this way (i.e. by specifying them within a connection header):

  • X-Forwarded-Host
  • X-Forwarded-Port
  • X-Forwarded-Proto
  • X-Real-Ip
  • Forwarded

PoC

The following docker-compose file was used for testing:

version: '3'
services:
  fabio:
    image: fabiolb/fabio
    ports:
      - "3000:9999"
      - "9998:9998"
    volumes:
      - ./fabio.properties:/etc/fabio/fabio.properties

  backend:
    build: .
    ports:
      - "8080:8080"
    environment:
      - PYTHONUNBUFFERED=1

The fabio.properties configuration:

proxy.addr = :9999
ui.addr = :9998
registry.backend = static
registry.static.routes = route add service / http://backend:8080/

A Python container runs a simple HTTP server that logs received headers. The Dockerfile:

FROM python:3.11-slim

WORKDIR /app

COPY app.py .

RUN pip install flask

EXPOSE 8080

CMD ["python", "app.py"]

Python Flask Server

from flask import Flask, request
import sys
import os

sys.stdout.flush()
sys.stderr.flush()
os.environ['PYTHONUNBUFFERED'] = '1'

app = Flask(__name__)

@app.before_request
def log_request_info():
    print("HEADERS:")
    for header_name, header_value in request.headers:
        print(f"   {header_name}: {header_value}")

@app.route("/", methods=['GET', 'POST', 'PUT', 'DELETE', 'PATCH'])
def hello():
    return f"Hello, World! Method: {request.method}"

@app.route("/<path:path>", methods=['GET', 'POST', 'PUT', 'DELETE', 'PATCH'])
def catch_all(path):
    return f"Caught path: {path}, Method: {request.method}"

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8080, debug=True)

A normal HTTP request/response pair looks like this:

Request

GET / HTTP/1.1
Host: 127.0.0.1:3000
User-Agent: curl/8.7.1
Accept: */*
Connection: keep-alive

curl command

curl --path-as-is -i -s -k -X $'GET' \
    -H $'Host: 127.0.0.1:3000' -H $'User-Agent: curl/8.7.1' -H $'Accept: */*' -H $'Connection: keep-alive' \
    $'http://127.0.0.1:3000/'

Response

HTTP/1.1 200 OK
Server: Werkzeug/3.1.3 Python/3.11.12
Date: Thu, 22 May 2025 23:09:12 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 25
Connection: close

Hello, World! Method: GET

Server Log

backend-1  | HEADERS:
backend-1  |    Host: 127.0.0.1:3000
backend-1  |    User-Agent: curl/8.7.1
backend-1  |    Accept: */*
backend-1  |    Forwarded: for=192.168.65.1; proto=http; by=172.24.0.3; httpproto=http/1.1
backend-1  |    X-Forwarded-For: 192.168.65.1
backend-1  |    X-Forwarded-Host: 127.0.0.1:3000
backend-1  |    X-Forwarded-Port: 3000
backend-1  |    X-Forwarded-Proto: http
backend-1  |    X-Real-Ip: 192.168.65.1

Next, a request, where the Forwarded header is defined as a hop-by-hop header via the Connection header is sent:

Request

GET / HTTP/1.1
Host: 127.0.0.1:3000
User-Agent: curl/8.7.1…
Record
GHSA-q7p4-7xjv-j3wf
CVSS 3.1
9.1 CriticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N
Weakness
CWE-345, CWE-348
Updated
2026-11-02
NVD 9.1

Fabio is an HTTP(S) and TCP router for deploying applications managed by consul. Prior to version 1.6.6, Fabio allows clients to remove X-Forwarded headers (except X-Forwarded-For) due to a vulnerability in how it processes hop-by-hop headers. Fabio adds HTTP headers like X-Forwarded-Host and X-Forwarded-Port when routing requests to backend applications. Since the receiving application should trust these headers, allowing HTTP clients to remove or modify them creates potential security vulnerabilities. Some of these custom headers can be removed and, in certain cases, manipulated. The attack relies on the behavior that headers can be defined as hop-by-hop via the HTTP Connection header. This issue has been patched in version 1.6.6.

Record
CVE-2025-48865
CVSS 3.1
9.1 CriticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N
Weakness
CWE-345, CWE-348
Updated
2026-11-02
OSV 9.1

Fabio allows HTTP clients to manipulate custom headers it adds

Fabio is an HTTP(S) and TCP router for deploying applications managed by consul. Prior to version 1.6.6, Fabio allows clients to remove X-Forwarded headers (except X-Forwarded-For) due to a vulnerability in how it processes hop-by-hop headers. Fabio adds HTTP headers like X-Forwarded-Host and X-Forwarded-Port when routing requests to backend applications. Since the receiving application should trust these headers, allowing HTTP clients to remove or modify them creates potential security vulnerabilities. Some of these custom headers can be removed and, in certain cases, manipulated. The attack relies on the behavior that headers can be defined as hop-by-hop via the HTTP Connection header. This issue has been patched in version 1.6.6.

Record
CVE-2025-48865
CVSS 3.1
9.1 CriticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N
Weakness
CWE-345, CWE-348
Updated
2026-11-02
OSVGHSA-q7p4-7xjv-j3wf 9.1

Fabio allows HTTP clients to manipulate custom headers it adds

Summary

Fabio allows clients to remove X-Forwarded headers (except X-Forwarded-For) due to a vulnerability in how it processes hop-by-hop headers.

Fabio adds HTTP headers like X-Forwarded-Host and X-Forwarded-Port when routing requests to backend applications. Since the receiving application should trust these headers, allowing HTTP clients to remove or modify them creates potential security vulnerabilities.

However, it was found that some of these custom headers can indeed be removed and, in certain cases, manipulated. The attack relies on the behavior that headers can be defined as hop-by-hop via the HTTP Connection header. By setting the following connection header, the X-Forwarded-Host header can, for example, be removed:

Connection: close, X-Forwarded-Host

Similar critical vulnerabilities have been identified in other web servers and proxies, including CVE-2022-31813 in Apache HTTP Server and CVE-2024-45410 in Traefik.

Details

It was found that the following headers can be removed in this way (i.e. by specifying them within a connection header):

  • X-Forwarded-Host
  • X-Forwarded-Port
  • X-Forwarded-Proto
  • X-Real-Ip
  • Forwarded

PoC

The following docker-compose file was used for testing:

version: '3'
services:
  fabio:
    image: fabiolb/fabio
    ports:
      - "3000:9999"
      - "9998:9998"
    volumes:
      - ./fabio.properties:/etc/fabio/fabio.properties

  backend:
    build: .
    ports:
      - "8080:8080"
    environment:
      - PYTHONUNBUFFERED=1

The fabio.properties configuration:

proxy.addr = :9999
ui.addr = :9998
registry.backend = static
registry.static.routes = route add service / http://backend:8080/

A Python container runs a simple HTTP server that logs received headers. The Dockerfile:

FROM python:3.11-slim

WORKDIR /app

COPY app.py .

RUN pip install flask

EXPOSE 8080

CMD ["python", "app.py"]

Python Flask Server

from flask import Flask, request
import sys
import os

sys.stdout.flush()
sys.stderr.flush()
os.environ['PYTHONUNBUFFERED'] = '1'

app = Flask(__name__)

@app.before_request
def log_request_info():
    print("HEADERS:")
    for header_name, header_value in request.headers:
        print(f"   {header_name}: {header_value}")

@app.route("/", methods=['GET', 'POST', 'PUT', 'DELETE', 'PATCH'])
def hello():
    return f"Hello, World! Method: {request.method}"

@app.route("/<path:path>", methods=['GET', 'POST', 'PUT', 'DELETE', 'PATCH'])
def catch_all(path):
    return f"Caught path: {path}, Method: {request.method}"

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8080, debug=True)

A normal HTTP request/response pair looks like this:

Request

GET / HTTP/1.1
Host: 127.0.0.1:3000
User-Agent: curl/8.7.1
Accept: */*
Connection: keep-alive

curl command

curl --path-as-is -i -s -k -X $'GET' \
    -H $'Host: 127.0.0.1:3000' -H $'User-Agent: curl/8.7.1' -H $'Accept: */*' -H $'Connection: keep-alive' \
    $'http://127.0.0.1:3000/'

Response

HTTP/1.1 200 OK
Server: Werkzeug/3.1.3 Python/3.11.12
Date: Thu, 22 May 2025 23:09:12 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 25
Connection: close

Hello, World! Method: GET

Server Log

backend-1  | HEADERS:
backend-1  |    Host: 127.0.0.1:3000
backend-1  |    User-Agent: curl/8.7.1
backend-1  |    Accept: */*
backend-1  |    Forwarded: for=192.168.65.1; proto=http; by=172.24.0.3; httpproto=http/1.1
backend-1  |    X-Forwarded-For: 192.168.65.1
backend-1  |    X-Forwarded-Host: 127.0.0.1:3000
backend-1  |    X-Forwarded-Port: 3000
backend-1  |    X-Forwarded-Proto: http
backend-1  |    X-Real-Ip: 192.168.65.1

Next, a request, where the Forwarded header is defined as a hop-by-hop header via the Connection header is sent:

Request

GET / HTTP/1.1
Host: 127.0.0.1:3000
User-Agent: curl/8.7.1…
Record
GHSA-q7p4-7xjv-j3wf
CVSS 3.1
9.1 CriticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N
Weakness
CWE-345, CWE-348
Updated
2026-11-02
OSVGO-2025-3722 No score

Fabio allows HTTP clients to manipulate custom headers it adds in github.com/fabiolb/fabio

Fabio allows HTTP clients to manipulate custom headers it adds in github.com/fabiolb/fabio

Record
GO-2025-3722
Updated
2026-11-02
OSVopenSUSE-SU-2025:15225-1 No score

govulncheck-vulndb-0.0.20250612T141001-1.1 on GA media

These are all security issues fixed in the govulncheck-vulndb-0.0.20250612T141001-1.1 package on the GA media of openSUSE Tumbleweed.

Record
openSUSE-SU-2025:15225-1
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
github.com/fabiolb/fabio
Go
through 1.6.5
1.6.6
github.com/fabiolb/fabio
Go
before 1.6.6
1.6.6
govulncheck-vulndb
openSUSE:Tumbleweed
From an advisory covering 29 CVEs
before 0.0.20250612T141001-1.1
0.0.20250612T141001-1.1

History

History
RecordedChangedSources
affected, facts
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2025-48865 is a critical vulnerability (CVSS 9.1) in Fabiolb Fabio, published May 29, 2025. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.47%, the 40th percentile. Fixed in github.com/fabiolb/fabio 1.6.6.

References

Show 30 moreShow less
This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open