ghsa-hm36-ffrh-c77c
Vulnerability from github
Published
2025-10-06 20:18
Modified
2025-10-06 20:18
Summary
Litestar X-Forwarded-For Header Spoofing Vulnerability Enables Rate Limit Evasion
Details

While testing Litestar's RateLimitMiddleware, it was discovered that rate limits can be completely bypassed by manipulating the X-Forwarded-For header. This renders IP-based rate limiting ineffective against determined attackers.

The Problem

Litestar's RateLimitMiddleware uses cache_key_from_request() to generate cache keys for rate limiting. When an X-Forwarded-For header is present, the middleware trusts it unconditionally and uses its value as part of the client identifier.

Since clients can set arbitrary X-Forwarded-For values, each different spoofed IP creates a separate rate limit bucket. An attacker can rotate through different header values to avoid hitting any single bucket's limit.

Looking at the relevant code in litestar/middleware/rate_limit.py around line 127, there's no validation of proxy headers or configuration for trusted proxies.

Reproduction Steps

Here's a minimal test case:

```python from litestar import Litestar, get from litestar.middleware.rate_limit import RateLimitConfig import uvicorn

@get("/api/data") def get_data() -> dict: return {"message": "sensitive data"}

rate_config = RateLimitConfig(rate_limit=("minute", 2))

app = Litestar( route_handlers=[get_data], middleware=[rate_config.middleware] )

if name == "main": uvicorn.run(app, host="0.0.0.0", port=8000) ```

Testing the bypass:

```bash

Normal requests get rate limited after 2 requests

curl http://localhost:8000/api/data # 200 OK curl http://localhost:8000/api/data # 200 OK
curl http://localhost:8000/api/data # 429 Too Many Requests

But spoofing X-Forwarded-For bypasses the limit entirely

curl -H "X-Forwarded-For: 192.168.1.100" http://localhost:8000/api/data # 200 OK curl -H "X-Forwarded-For: 192.168.1.101" http://localhost:8000/api/data # 200 OK curl -H "X-Forwarded-For: 192.168.1.102" http://localhost:8000/api/data # 200 OK ```

Security Impact

This vulnerability has several concerning implications:

Brute Force Protection Bypass: Authentication endpoints protected by rate limiting become vulnerable to credential stuffing attacks. An attacker can attempt thousands of login combinations from a single source.

API Abuse: Public APIs relying on rate limiting for abuse prevention can be scraped or hammered without restriction.

Resource Exhaustion: While not a traditional DoS, the ability to bypass rate limits means attackers can consume more server resources than intended.

The issue is particularly problematic because many developers deploy Litestar applications directly (not behind a proxy) during development or in containerized environments, making this attack vector accessible.

Potential Solutions

After reviewing how other frameworks handle this:

  • Default to socket IP only: Don't trust proxy headers unless explicitly configured
  • Trusted proxy configuration: Add settings to specify which proxy IPs are allowed to set forwarded headers
  • Header validation: Implement basic validation of forwarded IP formats

Django handles this through SECURE_PROXY_SSL_HEADER and trusted proxy lists. Express.js has similar trusted proxy configurations.

For immediate mitigation, applications can deploy behind a properly configured reverse proxy that strips/overwrites client-controllable headers before they reach Litestar.

Environment Details

  • Litestar version: 2.17.0
  • Python: 3.11

This affects any Litestar application using RateLimitMiddleware with default settings, which likely includes most applications that implement rate limiting.

Show details on source website


{
  "affected": [
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "litestar"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.17.0"
            },
            {
              "fixed": "2.18.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ],
      "versions": [
        "2.17.0"
      ]
    }
  ],
  "aliases": [
    "CVE-2025-59152"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-807"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2025-10-06T20:18:00Z",
    "nvd_published_at": "2025-10-06T16:15:34Z",
    "severity": "HIGH"
  },
  "details": "While testing Litestar\u0027s RateLimitMiddleware, it was discovered that rate limits can be completely bypassed by manipulating the X-Forwarded-For header. This renders IP-based rate limiting ineffective against determined attackers.\n\n## The Problem\n\nLitestar\u0027s RateLimitMiddleware uses `cache_key_from_request()` to generate cache keys for rate limiting. When an X-Forwarded-For header is present, the middleware trusts it unconditionally and uses its value as part of the client identifier.\n\nSince clients can set arbitrary X-Forwarded-For values, each different spoofed IP creates a separate rate limit bucket. An attacker can rotate through different header values to avoid hitting any single bucket\u0027s limit.\n\nLooking at the relevant code in `litestar/middleware/rate_limit.py` around [line 127](https://github.com/litestar-org/litestar/blob/26f20ac6c52de2b4bf81161f7560c8bb4af6f382/litestar/middleware/rate_limit.py#L127), there\u0027s no validation of proxy headers or configuration for trusted proxies.\n\n## Reproduction Steps\n\nHere\u0027s a minimal test case:\n\n```python\nfrom litestar import Litestar, get\nfrom litestar.middleware.rate_limit import RateLimitConfig\nimport uvicorn\n\n@get(\"/api/data\")\ndef get_data() -\u003e dict:\n    return {\"message\": \"sensitive data\"}\n\nrate_config = RateLimitConfig(rate_limit=(\"minute\", 2))\n\napp = Litestar(\n    route_handlers=[get_data],\n    middleware=[rate_config.middleware]\n)\n\nif __name__ == \"__main__\":\n    uvicorn.run(app, host=\"0.0.0.0\", port=8000)\n```\n\nTesting the bypass:\n\n```bash\n# Normal requests get rate limited after 2 requests\ncurl http://localhost:8000/api/data  # 200 OK\ncurl http://localhost:8000/api/data  # 200 OK  \ncurl http://localhost:8000/api/data  # 429 Too Many Requests\n\n# But spoofing X-Forwarded-For bypasses the limit entirely\ncurl -H \"X-Forwarded-For: 192.168.1.100\" http://localhost:8000/api/data  # 200 OK\ncurl -H \"X-Forwarded-For: 192.168.1.101\" http://localhost:8000/api/data  # 200 OK\ncurl -H \"X-Forwarded-For: 192.168.1.102\" http://localhost:8000/api/data  # 200 OK\n```\n\n## Security Impact\n\nThis vulnerability has several concerning implications:\n\nBrute Force Protection Bypass: Authentication endpoints protected by rate limiting become vulnerable to credential stuffing attacks. An attacker can attempt thousands of login combinations from a single source.\n\nAPI Abuse: Public APIs relying on rate limiting for abuse prevention can be scraped or hammered without restriction.\n\nResource Exhaustion: While not a traditional DoS, the ability to bypass rate limits means attackers can consume more server resources than intended.\n\nThe issue is particularly problematic because many developers deploy Litestar applications directly (not behind a proxy) during development or in containerized environments, making this attack vector accessible.\n\n## Potential Solutions\n\nAfter reviewing how other frameworks handle this:\n\n- Default to socket IP only: Don\u0027t trust proxy headers unless explicitly configured\n- Trusted proxy configuration: Add settings to specify which proxy IPs are allowed to set forwarded headers\n- Header validation: Implement basic validation of forwarded IP formats\n\nDjango handles this through `SECURE_PROXY_SSL_HEADER` and trusted proxy lists. Express.js has similar trusted proxy configurations.\n\nFor immediate mitigation, applications can deploy behind a properly configured reverse proxy that strips/overwrites client-controllable headers before they reach Litestar.\n\n## Environment Details\n\n- Litestar version: 2.17.0\n- Python: 3.11\n\nThis affects any Litestar application using RateLimitMiddleware with default settings, which likely includes most applications that implement rate limiting.",
  "id": "GHSA-hm36-ffrh-c77c",
  "modified": "2025-10-06T20:18:00Z",
  "published": "2025-10-06T20:18:00Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/litestar-org/litestar/security/advisories/GHSA-hm36-ffrh-c77c"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-59152"
    },
    {
      "type": "WEB",
      "url": "https://github.com/litestar-org/litestar/commit/42a89e043e50b515f8548a93954fe143f63cf9fb"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/litestar-org/litestar"
    },
    {
      "type": "WEB",
      "url": "https://github.com/litestar-org/litestar/blob/26f20ac6c52de2b4bf81161f7560c8bb4af6f382/litestar/middleware/rate_limit.py#L127"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Litestar X-Forwarded-For Header Spoofing Vulnerability Enables Rate Limit Evasion"
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Sightings

Author Source Type Date

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or seen somewhere by the user.
  • Confirmed: The vulnerability is confirmed from an analyst perspective.
  • Exploited: This vulnerability was exploited and seen by the user reporting the sighting.
  • Patched: This vulnerability was successfully patched by the user reporting the sighting.
  • Not exploited: This vulnerability was not exploited or seen by the user reporting the sighting.
  • Not confirmed: The user expresses doubt about the veracity of the vulnerability.
  • Not patched: This vulnerability was not successfully patched by the user reporting the sighting.


Loading…