Starlette: Arbitrary HTTP method dispatched to `HTTPEndpoint` attributes via `getattr`
Description
In Starlette's HTTPEndpoint, a non-standard HTTP method triggers arbitrary attribute lookup via getattr, bypassing intended handler restrictions.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
In Starlette's HTTPEndpoint, a non-standard HTTP method triggers arbitrary attribute lookup via getattr, bypassing intended handler restrictions.
Vulnerability
The vulnerability exists in Starlette's HTTPEndpoint class, where the HTTP method string from the request is lowercased and used to look up an attribute with getattr without validating against a set of supported HTTP verbs. When an HTTPEndpoint subclass is registered through Route(...) without an explicit methods= argument, any HTTP method (including non-standard ones) reaches the endpoint. This affects all versions of Starlette using this pattern, and by extension frameworks like FastAPI. [1][2]
Exploitation
An attacker needs only the ability to send HTTP requests to an endpoint using an HTTPEndpoint subclass registered without a restricted methods= argument. By crafting a request with a non-standard HTTP method such as _DO_DELETE (whose lowercased form _do_delete matches an attribute on the subclass), the attacker can cause that attribute to be invoked as a handler, bypassing any authorization checks that would normally be applied by the intended public handler. [1][2]
Impact
If the matched attribute is an internal helper method that accepts a single request argument and returns a response, the attacker can invoke it directly. The impact varies depending on the behavior of the exposed method, potentially leading to information disclosure, privilege escalation, or other unintended actions. The attacker bypasses the authorization controls that the intended public handler would enforce. [1][2]
Mitigation
The primary mitigation is to register HTTPEndpoint subclasses with an explicit methods= argument on Route, listing only the supported HTTP verbs. This causes the route to reject any other method with a 405 Method Not Allowed response before it reaches the endpoint. As of publication, no patched version has been announced; the workaround is to always specify the methods= argument. [1][2]
AI Insight generated on Jun 15, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
2Patches
1e3f972225adbOnly dispatch standard HTTP verbs in `HTTPEndpoint` (#3286)
2 files changed · +22 −1
starlette/endpoints.py+5 −1 modified@@ -33,7 +33,11 @@ async def dispatch(self) -> None: request = Request(self.scope, receive=self.receive) handler_name = "get" if request.method == "HEAD" and not hasattr(self, "head") else request.method.lower() - handler: Callable[[Request], Any] = getattr(self, handler_name, self.method_not_allowed) + handler: Callable[[Request], Any] + if request.method in self._allowed_methods or (request.method == "HEAD" and "GET" in self._allowed_methods): + handler = getattr(self, handler_name) + else: + handler = self.method_not_allowed is_async = is_async_callable(handler) if is_async: response = await handler(request)
tests/test_endpoints.py+17 −0 modified@@ -47,6 +47,23 @@ def test_http_endpoint_route_method(client: TestClient) -> None: assert response.headers["allow"] == "GET" +def test_http_endpoint_does_not_dispatch_non_verb_method(test_client_factory: TestClientFactory) -> None: + class Endpoint(HTTPEndpoint): + async def get(self, request: Request) -> PlainTextResponse: + return PlainTextResponse("Hello, world!") # pragma: no cover + + async def _do_delete(self, request: Request) -> PlainTextResponse: + return PlainTextResponse("Privileged helper") # pragma: no cover + + app = Router(routes=[Route("/", endpoint=Endpoint)]) + client = test_client_factory(app) + + response = client.request("_DO_DELETE", "/") + assert response.status_code == 405 + assert response.text == "Method Not Allowed" + assert response.headers["allow"] == "GET" + + def test_websocket_endpoint_on_connect(test_client_factory: TestClientFactory) -> None: class WebSocketApp(WebSocketEndpoint): async def on_connect(self, websocket: WebSocket) -> None:
Vulnerability mechanics
Root cause
"HTTPEndpoint uses externally-controlled HTTP method names as attribute selectors via getattr without validating the method against the set of allowed HTTP verbs."
Attack vector
An attacker sends an HTTP request with a non-standard method token (e.g., `_DO_DELETE`) to a `Route` that registers an `HTTPEndpoint` subclass without an explicit `methods=` argument. Because the route does not constrain the method, the request reaches the endpoint, where `HTTPEndpoint.dispatch` lowercases the method name and uses `getattr` to look up an attribute on the subclass. If the subclass defines a method whose name matches the lowercased token (e.g., `_do_delete`), that method is invoked as a handler, bypassing any authorization or access controls that the intended public handlers enforce. [CWE-470]
What the fix does
The patch adds a guard in `HTTPEndpoint.dispatch` that checks whether `request.method` is in `self._allowed_methods` before performing the `getattr` lookup. If the method is not allowed (and it is not a HEAD request for a GET handler), the endpoint immediately returns `405 Method Not Allowed` via `self.method_not_allowed`. This prevents any non-standard HTTP method from reaching the attribute-resolution step, so internal helpers like `_do_delete` can never be invoked through a crafted method token. [patch_id=6110801]
Preconditions
- configThe application registers an HTTPEndpoint subclass via Route(...) without an explicit methods= argument.
- configThe endpoint subclass defines additional methods whose lowercased name matches a non-standard HTTP method token and that accept a single request argument.
- networkThe attacker can send arbitrary HTTP method tokens to the endpoint.
Generated on Jun 15, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
2News mentions
0No linked articles in our index yet.