VYPR
Medium severity5.3GHSA Advisory· Published Jun 15, 2026· Updated Jun 15, 2026

Starlette: Arbitrary HTTP method dispatched to `HTTPEndpoint` attributes via `getattr`

CVE-2026-48817

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

2

Patches

1
e3f972225adb

Only dispatch standard HTTP verbs in `HTTPEndpoint` (#3286)

https://github.com/kludex/starletteMarcelo TrylesinskiMay 23, 2026Fixed in 1.1.0via llm-release-walk
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

2

News mentions

0

No linked articles in our index yet.