Skip to content
Go back

[CVE-2025-46814] FastAPI Guard’s X-Forwarded-For Handling Lets Attackers Impersonate Trusted IPs

Volerion Research

TL;DR
A flaw in how fastapi-guard parses the X-Forwarded-For header means any client can forge the source IP address that the application logic sees. If an API relies on that header for allow-listing or rate limiting the attacker simply adds a second comma-separated value and walks right in. The fix ships in version 2.0.0 and upgrading is trivial.


1. Summary

CVE ID CVE-2025-46814
Affected Product(s) fastapi-guard < 2.0.0 when get_client_ip() or IP-based dependencies are in use
Volerion Risk Score 8.7 / 10
Exploit Status Public PoC included in GitHub advisory
CISA KEV No

Applications that gate specific endpoints behind a reverse-proxy aware IP check are vulnerable. By sending X-Forwarded-For: 203.0.113.10, 127.0.0.1 the attacker convinces fastapi-guard that the request originated from the trusted loopback address.


2. Context – Why this bug matters to every Python API behind a proxy

FastAPI exploded in popularity because it delivers Django-level ergonomics with raw ASGI speed. Security best practice dictates putting a TLS-terminating proxy such as Nginx or Traefik in front of the application workers. As soon as you do that you need a way to recover the real client IP. Many developers reach for fastapi-guard’s helper get_client_ip(), which promises to do the right thing.

The helper looks at the last value of X-Forwarded-For when behind a proxy or the client tuple otherwise. Unfortunately the pre-2.0.0 implementation split the header by commas but never stripped whitespace or verified that only a single address was present. An attacker therefore adds an extra address and tricks the logic.

Because IP based checks are often used for highly privileged endpoints such as /admin or internal health paths the consequence can be immediate authentication bypass.


3. Technical Details – A two-character injection

The vulnerable code in fastapi_guard/utils.py resembled the following:

def get_client_ip(request: Request) -> str:
    if "X-Forwarded-For" in request.headers:
        return request.headers["X-Forwarded-For"].split(",")[-1]
    return request.client.host

The developer intended to take the last element because many proxies append the original IP at the end. The oversight is that an attacker controls the entire header if the edge proxy does not overwrite it, so they can supply two addresses.

A working curl demonstration against a default FastAPI app that guards /admin looks like this:

curl -H "X-Forwarded-For: 203.0.113.10, 127.0.0.1" https://api.example.com/admin

If 127.0.0.1 is on the allow-list the request sails through. Log aggregators and analytics platforms that rely on the same helper will record the forged address, hiding the attacker’s real origin.

Version 2.0.0 rewrites the helper to:

ip_str = request.headers.get("X-Forwarded-For", "")
ips = [ip.strip() for ip in ip_str.split(",") if ip.strip()]
if len(ips) != 1:
    raise ValueError("Invalid X-Forwarded-For chain")
return ips[0]

The new logic enforces exactly one address and strips whitespace, closing the hole.


4. Impact – Bypassed allow-lists, poisoned logs and misleading rate limits

On its own the bug is not remote code execution, yet it directly undermines several practical defenses that web services depend on:

• IP allow-lists that restrict sensitive routes become ineffective.
• Application level rate limiting that keys on source IP no longer throttles attackers.
• Security analytics, SIEM correlation and audit records store the spoofed address, delaying incident response.

When combined with a vulnerable business logic route the issue escalates to full account takeover or data exfiltration. Cloud environments where internal metadata services are guarded only by IP checks are particularly exposed.


5. Remediation – Upgrade or enforce proxy sanitation

The vendor released fastapi-guard 2.0.0 on 7 May 2025. Upgrading the dependency is a single line in requirements.txt:

fastapi-guard>=2.0.0

If an upgrade cannot happen immediately you can mitigate by configuring the edge proxy to override X-Forwarded-For and discard any existing header:

# Nginx snippet
proxy_set_header X-Forwarded-For $remote_addr;

Relying on middleware to strip additional addresses before reaching FastAPI is another stopgap but upgrading remains the definitive fix.


6. Timeline

Date (UTC)Milestone
2025-05-06CVE-2025-46814 published on GitHub advisory feed
2025-05-06Volerion completes enrichment and publishes risk score
2025-05-07fastapi-guard 2.0.0 released with input validation fix

7. References


About Volerion

Volerion delivers AI driven enrichment minutes after a CVE goes live. A single call to our REST API returns CVSS 4.0 vectors, exploitability metrics and affected products complete with remediation. Additionally, we offer different scoring profiles, complete with insight into the eight comprehensive categories that make up the final score. Our API is also available in the traditional NVD API 2.0 format, so integration is as simple as swapping hosts. Spend less time parsing CVEs and more time closing them.

How the Volerion Risk Score Fits With CVSS, EPSS and KEV

At the time of writing:

The Volerion Risk Score of 8.7 folds in exploit maturity, dependency prevalence in public images and the trivial remediation path. The higher number signals that defenders should still prioritise the patch even though CVSS and EPSS alone might suggest otherwise.


Share this post on:

Previous Post
[CVE-2025-4396] Unauthenticated SQL Injection in Relevanssi Gives Attackers a Direct Line to Your WordPress Database
Next Post
[CVE-2025-32433] Erlang/OTP SSH Authentication Bypass Gives Attackers a Direct Shell