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-06 | CVE-2025-46814 published on GitHub advisory feed |
| 2025-05-06 | Volerion completes enrichment and publishes risk score |
| 2025-05-07 | fastapi-guard 2.0.0 released with input validation fix |
7. References
- GitHub advisory: https://github.com/rennf93/fastapi-guard/security/advisories/GHSA-77q8-qmj7-x7pp
- Patch commit: https://github.com/rennf93/fastapi-guard/commit/0b003fda4c678c1b514e95f319aee88113e9bf4b
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:
- This CVE is scored at 3.4 using CVSS 3.1, reflecting limited confidentiality impact under the base metric but not considering real-world misuse.
- EPSS assigns a probability of 0.00085 that exploitation will occur in the next 30 days, a figure that often underestimates low complexity web issues.
- CISA has not added the vulnerability to KEV, so US federal patch deadlines do not yet apply.
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.