Back to Blog
critical SEVERITY6 min read

How Rate Limiting Vulnerabilities Happen in FastAPI and How to Fix Them

A critical denial-of-service vulnerability was discovered in a FastAPI application controlling Tesla Powerwall systems, where all 113+ API endpoints—including critical control endpoints for `/control/reserve` and `/control/mode`—lacked any rate limiting protection. An attacker could flood these endpoints with unlimited requests, exhausting server resources and disrupting powerwall monitoring and control operations. The fix introduces a configurable, pure-ASGI rate limiting middleware that can be

O
By Orbis AppSec
Published August 31, 2026Reviewed August 31, 2026

Answer Summary

This is a Denial of Service (DoS) vulnerability caused by missing rate limiting in a FastAPI application (CWE-770: Allocation of Resources Without Limits). The Python application exposed 113+ endpoints including critical powerwall control APIs without request throttling. The fix implements a configurable fixed-window rate limiting middleware (`_RateLimitMiddleware`) that can be enabled via the `PW_RATE_LIMIT_ENABLED` environment variable, with tunable limits for requests per window, window duration, and maximum tracked client buckets.

Vulnerability at a Glance

cweCWE-770
fixImplemented configurable ASGI rate limiting middleware with environment variable controls
riskRemote attackers can exhaust server resources and disrupt powerwall control operations
languagePython (FastAPI)
root causeNo request throttling middleware on any of the 113+ API endpoints
vulnerabilityMissing Rate Limiting (Denial of Service)

Introduction

In a FastAPI application designed to monitor and control Tesla Powerwall systems, we discovered a critical denial-of-service vulnerability in app/main.py. The application exposed over 113 API endpoints—including sensitive control endpoints like /control/reserve and /control/mode—without any form of request throttling or rate limiting.

This meant that any attacker with network access to the application could send unlimited HTTP requests to any endpoint, potentially exhausting CPU, memory, and database connections. For an application controlling home energy storage systems, this vulnerability could disrupt critical powerwall monitoring and control operations, leaving users unable to manage their energy systems during peak demand or outages.

The vulnerable code pattern was straightforward: a FastAPI application with numerous routes but no middleware to limit request rates. While the application had proper authentication in place, it lacked the crucial defense-in-depth measure of rate limiting.

The Vulnerability Explained

What Makes This Dangerous?

The FastAPI application in app/main.py instantiated routes for various functionalities without any rate limiting middleware in the ASGI middleware stack. This created a situation where:

  1. Control endpoints (/control/reserve, /control/mode) could be flooded with commands
  2. Data endpoints (/api/gateways/*, /api/timeseries/*) could be overwhelmed with read requests
  3. Health endpoints (/health) could be targeted to mask actual service degradation

The original application structure looked something like this:

from fastapi import FastAPI

app = FastAPI()

# 113+ endpoints defined without any rate limiting
@app.post("/control/reserve")
async def control_reserve():
    # Critical powerwall control logic
    pass

@app.post("/control/mode")
async def control_mode(mode: dict):
    # Mode switching logic
    pass

@app.get("/api/gateways/status")
async def gateway_status():
    # Gateway status retrieval
    pass

Attack Scenario

An attacker targeting this powerwall monitoring system could execute a denial-of-service attack with a simple script:

import asyncio
import aiohttp

async def flood_endpoint():
    async with aiohttp.ClientSession() as session:
        while True:
            # Flood the control endpoint
            await session.post("http://target/control/mode", 
                             json={"mode": "self_consumption"})

This attack would:
1. Exhaust the server's ability to process legitimate requests
2. Potentially cause database connection pool exhaustion
3. Disrupt real-time powerwall monitoring during critical periods
4. Prevent legitimate users from controlling their energy systems

The DESIGN.md file explicitly documented this as a critical issue, noting that "a compromised token could flood the Powerwall with commands."

The Fix

The fix introduces a configurable, pure-ASGI rate limiting middleware called _RateLimitMiddleware that can be enabled via environment variables. This approach was chosen over the originally suggested slowapi route decorator for several important reasons:

Key Design Decisions

  1. Global application rather than per-route decoration
  2. Disabled by default to avoid breaking existing integrations (Powerwall-Dashboard, Grafana, Home Assistant polling)
  3. Configurable via environment variables for flexibility

The updated DESIGN.md reflects this resolution:

#### 1. ✅ No Rate Limiting on Control Endpoints — Addressed

**Location**: [app/api/legacy.py](app/api/legacy.py#L73-L87), [app/main.py](app/main.py) (`_RateLimitMiddleware`)

**Resolution**: A first-party, pure-ASGI, fixed-window rate limiter is available, 
applied globally (not just `/control/*`) rather than the originally-suggested 
`slowapi` route decorator. It is **disabled by default** (`PW_RATE_LIMIT_ENABLED`) 
so it never regresses the common Powerwall-Dashboard/Grafana/Home Assistant polling 
use case.

Configuration Options

The middleware is controlled through these environment variables:

Variable Purpose
PW_RATE_LIMIT_ENABLED Enable/disable rate limiting (default: off)
PW_RATE_LIMIT_MAX_REQUESTS Maximum requests per window
PW_RATE_LIMIT_WINDOW_SECONDS Time window duration
PW_RATE_LIMIT_MAX_BUCKETS Maximum tracked client buckets (memory bound)

Before vs. After

Before: No rate limiting middleware in the ASGI stack

app = FastAPI()
# All 113+ endpoints accessible without throttling

After: Configurable rate limiting middleware available

app = FastAPI()
# _RateLimitMiddleware added to middleware stack
# Controlled via PW_RATE_LIMIT_ENABLED environment variable
# Returns HTTP 429 when limits exceeded

The fix also updated the priority table in DESIGN.md:

| Priority | Area | Effort |
|----------|------|--------|
| ~~High~~ Done | ~~Rate limiting on control endpoints~~ Available via `PW_RATE_LIMIT_ENABLED` (default off) | Low |

Prevention & Best Practices

1. Always Include Rate Limiting in API Design

Rate limiting should be a first-class consideration when designing APIs, not an afterthought. Consider:

  • Endpoint sensitivity: Control endpoints need stricter limits than read-only endpoints
  • User tiers: Different rate limits for different authentication levels
  • Burst vs. sustained: Allow short bursts while limiting sustained traffic

2. Defense in Depth

The fix documentation wisely recommends pairing application-level rate limiting with infrastructure-level protection:

"the recommendation to pair this with a real reverse-proxy rate limiter for internet-exposed deployments"

Consider implementing rate limiting at multiple layers:
- Application level: FastAPI middleware (as implemented here)
- Reverse proxy: Nginx, HAProxy, or cloud load balancers
- CDN/WAF: Cloudflare, AWS WAF, or similar services

3. Configuration Best Practices

The fix demonstrates excellent configuration practices:

# Environment-variable driven configuration
# Allows different limits for dev/staging/production
# Disabled by default to avoid breaking existing integrations

4. Memory Management

The PW_RATE_LIMIT_MAX_BUCKETS configuration prevents memory exhaustion from tracking too many unique clients—an important consideration that prevents the rate limiter itself from becoming a DoS vector.

Key Takeaways

  • All 113+ endpoints in app/main.py were vulnerable to unlimited request flooding before this fix
  • Control endpoints like /control/reserve and /control/mode posed the highest risk as they directly affect powerwall operations
  • The fix uses a fixed-window algorithm with configurable parameters via environment variables
  • Disabled by default preserves backward compatibility with existing monitoring integrations
  • Memory is bounded via PW_RATE_LIMIT_MAX_BUCKETS to prevent the rate limiter from becoming an attack vector itself

How Orbis AppSec Detected This

  • Source: HTTP requests from any network client with access to the application
  • Sink: All 113+ API endpoints in app/main.py including /control/reserve, /control/mode, /api/gateways/*, and /api/timeseries/*
  • Missing control: No rate limiting middleware in the ASGI middleware stack to throttle incoming requests
  • CWE: CWE-770 (Allocation of Resources Without Limits or Throttling)
  • Fix: Implemented _RateLimitMiddleware as a configurable, pure-ASGI fixed-window rate limiter controlled via PW_RATE_LIMIT_ENABLED environment variable

Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.

Conclusion

This vulnerability demonstrates why rate limiting is a critical security control for any API, especially those controlling physical systems like energy storage. The fix provides a flexible, opt-in solution that protects against denial-of-service attacks while maintaining compatibility with existing monitoring integrations.

When building APIs with FastAPI or any other framework, always consider:
1. What happens if an endpoint receives thousands of requests per second?
2. Which endpoints are most critical and need the strictest limits?
3. How will rate limiting interact with legitimate high-frequency clients?

The configurable approach taken in this fix—disabled by default with environment variable controls—provides a template for implementing rate limiting in applications with diverse deployment scenarios.

References

Frequently Asked Questions

What is a rate limiting vulnerability?

A rate limiting vulnerability occurs when an application accepts unlimited requests from clients, allowing attackers to overwhelm server resources through request flooding, leading to denial of service.

How do you prevent rate limiting vulnerabilities in FastAPI?

Implement middleware that tracks request counts per client IP within time windows, returning HTTP 429 (Too Many Requests) when limits are exceeded. Use libraries like slowapi or custom ASGI middleware.

What CWE is missing rate limiting?

CWE-770: Allocation of Resources Without Limits or Throttling describes vulnerabilities where applications fail to limit resource consumption, enabling denial of service attacks.

Is authentication enough to prevent DoS attacks?

No, even authenticated endpoints need rate limiting. A compromised token or malicious authenticated user can still flood endpoints, and authentication itself consumes resources before rejection.

Can static analysis detect missing rate limiting?

Yes, static analysis tools can identify FastAPI applications without rate limiting middleware by analyzing the middleware stack and endpoint configurations, though manual review is often needed to assess appropriate limits.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #84

Related Articles

high

How Denial of Service via Infinite Loop in Nanoid happens in Node.js and how to fix it

A high-severity vulnerability in the nanoid package (CVE-2026-67213) could trigger an infinite loop in random ID generation when processing specially crafted input. This fix upgrades nanoid from version 3.3.12 to 3.3.18 and 5.1.6, eliminating the denial-of-service attack vector in the frontend application's dependency tree.

critical

How Supply Chain Vulnerabilities Happen in pnpm Workspaces and How to Fix Them

A critical supply chain vulnerability in a pnpm workspace configuration allowed immediate installation of newly published packages, exposing downstream consumers to potentially malicious dependencies. The fix adds `minimumReleaseAge: 10080` and two additional hardening directives to enforce a seven-day quarantine period.

critical

How Command Injection Happens in Python Flask Applications and How to Fix It

A critical command injection vulnerability was discovered in a Flask application where `subprocess.Popen` and `subprocess.run` were called with `shell=True`, allowing attackers to execute arbitrary system commands through shell metacharacters. The fix replaces dangerous shell execution with `shlex.split()` for proper argument parsing and sets `shell=False` to prevent command injection attacks.

critical

How Resource Exhaustion via Missing Fetch Timeouts Happens in Node.js and How to Fix It

A critical resource exhaustion vulnerability was discovered in the `dsh-plugin-marketplace` GitHub client where multiple `fetch()` calls in `lib/index.js` lacked timeout configuration. While one fetch call at line 1161 correctly used `AbortSignal.timeout()`, other calls at lines 101 and 145 had no timeout mechanism, allowing attackers to exhaust connection pools by targeting slow or unresponsive GitHub API endpoints. The fix ensures all fetch operations consistently apply the configurable `regis

high

How Denial of Service via Invalid Binary POST Requests happens in Socket.IO and how to fix it

A high-severity Denial of Service vulnerability (CVE-2026-59725) was discovered in engine.io versions prior to 6.6.7, where invalid binary POST requests could crash Socket.IO servers. The fix upgrades engine.io from 6.6.5 to 6.6.7, which includes improved validation for binary packet handling and prevents malformed requests from taking down real-time communication channels.

critical

How Cross-Site Scripting happens in fast-xml-parser and how to fix it

CVE-2026-25896 is a critical Cross-Site Scripting vulnerability in fast-xml-parser stemming from improper DOCTYPE entity handling, which could allow attackers to inject malicious scripts through crafted XML payloads. The fix upgrades the vulnerable dependency from version 4.4.1 to patched versions 5.3.5 and 4.5.4, eliminating the unsafe parsing behavior while preserving all legitimate XML processing functionality.