Every CVE Search/ Get API key

CVE-2026-114620

Authlib: Unvalidated request_uri fetch in JWT-secured authorization request (JAR) leading to SSRF

5.4 MediumFix available

Authlib is a Python library which builds OAuth and OpenID Connect servers. Prior to 1.9.0, Authlib's RFC 9101 JWTAuthenticationRequest passes the unauthenticated, client-controlled request_uri parameter to the abstract get_request_object() hook before applying a destination or registration policy; the hook itself performs no network request, while the documentation demonstrates an unrestricted HTTP fetch. In deployments whose integrator implements that hook as an unrestricted outbound fetch, a remote attacker who knows a valid public client identifier can make the authorization server request internal, link-local, or otherwise unintended URLs and can distinguish fetch outcomes through different error responses and timing. Deployments whose custom hook already applies a secure allowlist, destination controls, and retrieval limits are not affected. The JWTAuthenticationRequest implementation in authlib/oauth2/rfc9101/authorization_server.py forwards request_uri to get_request_object() before an application-approved retrieval policy accepts the destination. This issue is fixed in version 1.9.0.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
High
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
Low
Integrity
Low
Availability
None

Exploit likelihood

0.39%Up 0.1 points since Oct 23, 2026
90%50%10%1%

What each source reports

CVE List Score used 5.4

Authlib: Unvalidated request_uri fetch in JWT-secured authorization request (JAR) leading to SSRF

Authlib is a Python library which builds OAuth and OpenID Connect servers. Prior to 1.9.0, Authlib's RFC 9101 JWTAuthenticationRequest passes the unauthenticated, client-controlled request_uri parameter to the abstract get_request_object() hook before applying a destination or registration policy; the hook itself performs no network request, while the documentation demonstrates an unrestricted HTTP fetch. In deployments whose integrator implements that hook as an unrestricted outbound fetch, a remote attacker who knows a valid public client identifier can make the authorization server request internal, link-local, or otherwise unintended URLs and can distinguish fetch outcomes through different error responses and timing. Deployments whose custom hook already applies a secure allowlist, destination controls, and retrieval limits are not affected. The JWTAuthenticationRequest implementation in authlib/oauth2/rfc9101/authorization_server.py forwards request_uri to get_request_object() before an application-approved retrieval policy accepts the destination. This issue is fixed in version 1.9.0.

Record
CVE-2026-114620
CVSS 3.1
5.4 MediumCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:L/A:N
Weakness
CWE-918
Updated
2026-11-02
EUVDEUVD-2026-108522 5.4

Authlib is a Python library which builds OAuth and OpenID Connect servers. Prior to 1.9.0, Authlib's RFC 9101 JWTAuthenticationRequest passes the unauthenticated, client-controlled request_uri parameter to the abstract get_request_object() hook before applying a destination or registration policy; the hook itself performs no network request, while the documentation demonstrates an unrestricted HTTP fetch. In deployments whose integrator implements that hook as an unrestricted outbound fetch, a remote attacker who knows a valid public client identifier can make the authorization server request internal, link-local, or otherwise unintended URLs and can distinguish fetch outcomes through different error responses and timing. Deployments whose custom hook already applies a secure allowlist, destination controls, and retrieval limits are not affected. The JWTAuthenticationRequest implementation in authlib/oauth2/rfc9101/authorization_server.py forwards request_uri to get_request_object() before an application-approved retrieval policy accepts the destination. This issue is fixed in version 1.9.0.

Record
EUVD-2026-108522
CVSS 3.1
5.4 MediumCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:L/A:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-x4rv-c3wx-4cr8 5.4

Authlib: Unvalidated request_uri fetch in JWT-secured authorization request (JAR) leading to SSRF

Summary

Authlib's RFC 9101 (JAR) extension passes the attacker-controlled request_uri authorization parameter straight to the get_request_object() fetch hook with no validation, at a pre-authentication endpoint. Authlib already defines the pre-registration allowlist for this (request_uris client metadata and require_request_uri_registration server metadata) but the extension never consults it, and both docstrings instruct integrators to implement the hook as an unrestricted requests.get(request_uri). Deployments following the documented pattern get an unauthenticated SSRF primitive.

Details

Verified against authlib 1.7.2 and current main. All line numbers below are from authlib/oauth2/rfc9101/authorization_server.py.

The extension registers itself on the before_get_authorization_grant hook (lines 62-65), so it runs on every authorization request before any user or client authentication. support_request_uri defaults to True (line 58).

The only gate before the sink is that client_id names an existing client (lines 91-103). A client_id is a public, non-secret identifier.

The sink at line 159 forwards the raw parameter with no scheme, host, or allowlist check:

def _get_raw_request_object(self, request: OAuth2Request) -> str:
    if "request_uri" in request.payload.data:
        raw_request_object = self.get_request_object(
            request.payload.data["request_uri"]
        )
        if not raw_request_object:
            raise InvalidRequestUriError(state=request.payload.state)

get_request_object is abstract (line 213, raise NotImplementedError() at line 225), so authlib itself performs no outbound request. The defect is that authlib supplies unvalidated attacker input to that extension point and then documents the insecure implementation twice — in the class docstring (lines 34-38) and in the hook's own docstring (lines 218-223):

def get_request_object(self, request_uri: str):
    try:
        return requests.get(request_uri).text
    except requests.Exception:
        return None

Two points sharpen this beyond a generic documentation issue:

  • The allowlist already exists and is ignored. Authlib validates request_uris as client metadata (authlib/oauth2/rfc7591/claims.py:319) and require_request_uri_registration as server metadata (authlib/oauth2/rfc8414/models.py:263). The rfc9101 package contains zero references to either name, so the pre-registration model is never enforced at the point of use.
  • RFC 9101 §10.4.1 asks for controls that are absent. It states the server should "a) check that the value of the request_uri parameter does not point to an unexpected location, b) check that the media type of the response is application/oauth-authz-req+jwt, c) implement a timeout for obtaining the content of request_uri, and d) not perform recursive GET on the request_uri." The extension implements none of these and the documented example implements none of them either.

The two failure paths are distinguishable, which supplies the inference channel for a blind SSRF: a falsy fetch result raises InvalidRequestUriError (invalid_request_uri, lines 162-163), while a successful fetch of non-JWT content raises InvalidRequestObjectError (invalid_request_object, line 186).

PoC

This demonstrates the library-level defect with no network egress required: it shows the unvalidated URI reaching the fetch hook pre-authentication.

python -m venv .venv && .venv/bin/pip install authlib
from authlib.oauth2.rfc6749.requests import BasicOAuth2Payload, OAuth2Request
from authlib.oauth2.rfc9101 import JWTAuthenticationRequest

reached = []


class Extension(JWTAuthenticationRequest):
    def get_request_object(self, request_uri):
        reached.append(request_uri)  # the docstring puts requests.get(request_uri) here
        return None

    def resolve_client_public_key(self, client):
        return {"keys": []}
…
Record
GHSA-x4rv-c3wx-4cr8
CVSS 3.1
5.4 MediumCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:L/A:N
Weakness
CWE-918
Updated
2026-11-02
NVD 5.4

Authlib is a Python library which builds OAuth and OpenID Connect servers. Prior to 1.9.0, Authlib's RFC 9101 JWTAuthenticationRequest passes the unauthenticated, client-controlled request_uri parameter to the abstract get_request_object() hook before applying a destination or registration policy; the hook itself performs no network request, while the documentation demonstrates an unrestricted HTTP fetch. In deployments whose integrator implements that hook as an unrestricted outbound fetch, a remote attacker who knows a valid public client identifier can make the authorization server request internal, link-local, or otherwise unintended URLs and can distinguish fetch outcomes through different error responses and timing. Deployments whose custom hook already applies a secure allowlist, destination controls, and retrieval limits are not affected. The JWTAuthenticationRequest implementation in authlib/oauth2/rfc9101/authorization_server.py forwards request_uri to get_request_object() before an application-approved retrieval policy accepts the destination. This issue is fixed in version 1.9.0.

Record
CVE-2026-114620
CVSS 3.1
5.4 MediumCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:L/A:N
Weakness
CWE-918
Updated
2026-11-02
OSV 5.4

Authlib: Unvalidated request_uri fetch in JWT-secured authorization request (JAR) leading to SSRF

Authlib is a Python library which builds OAuth and OpenID Connect servers. Prior to 1.9.0, Authlib's RFC 9101 JWTAuthenticationRequest passes the unauthenticated, client-controlled request_uri parameter to the abstract get_request_object() hook before applying a destination or registration policy; the hook itself performs no network request, while the documentation demonstrates an unrestricted HTTP fetch. In deployments whose integrator implements that hook as an unrestricted outbound fetch, a remote attacker who knows a valid public client identifier can make the authorization server request internal, link-local, or otherwise unintended URLs and can distinguish fetch outcomes through different error responses and timing. Deployments whose custom hook already applies a secure allowlist, destination controls, and retrieval limits are not affected. The JWTAuthenticationRequest implementation in authlib/oauth2/rfc9101/authorization_server.py forwards request_uri to get_request_object() before an application-approved retrieval policy accepts the destination. This issue is fixed in version 1.9.0.

Record
CVE-2026-114620
CVSS 3.1
5.4 MediumCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:L/A:N
Weakness
CWE-918
Updated
2026-11-02
OSVDEBIAN-CVE-2026-114620 5.4

Authlib is a Python library which builds OAuth and OpenID Connect servers. Prior to 1.9.0, Authlib's RFC 9101 JWTAuthenticationRequest passes the unauthenticated, client-controlled request_uri parameter to the abstract get_request_object() hook before applying a destination or registration policy; the hook itself performs no network request, while the documentation demonstrates an unrestricted HTTP fetch. In deployments whose integrator implements that hook as an unrestricted outbound fetch, a remote attacker who knows a valid public client identifier can make the authorization server request internal, link-local, or otherwise unintended URLs and can distinguish fetch outcomes through different error responses and timing. Deployments whose custom hook already applies a secure allowlist, destination controls, and retrieval limits are not affected. The JWTAuthenticationRequest implementation in authlib/oauth2/rfc9101/authorization_server.py forwards request_uri to get_request_object() before an application-approved retrieval policy accepts the destination. This issue is fixed in version 1.9.0.

Record
DEBIAN-CVE-2026-114620
CVSS 3.1
5.4 MediumCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:L/A:N
Updated
2026-11-02
OSVGHSA-x4rv-c3wx-4cr8 5.4

Authlib: Unvalidated request_uri fetch in JWT-secured authorization request (JAR) leading to SSRF

Summary

Authlib's RFC 9101 (JAR) extension passes the attacker-controlled request_uri authorization parameter straight to the get_request_object() fetch hook with no validation, at a pre-authentication endpoint. Authlib already defines the pre-registration allowlist for this (request_uris client metadata and require_request_uri_registration server metadata) but the extension never consults it, and both docstrings instruct integrators to implement the hook as an unrestricted requests.get(request_uri). Deployments following the documented pattern get an unauthenticated SSRF primitive.

Details

Verified against authlib 1.7.2 and current main. All line numbers below are from authlib/oauth2/rfc9101/authorization_server.py.

The extension registers itself on the before_get_authorization_grant hook (lines 62-65), so it runs on every authorization request before any user or client authentication. support_request_uri defaults to True (line 58).

The only gate before the sink is that client_id names an existing client (lines 91-103). A client_id is a public, non-secret identifier.

The sink at line 159 forwards the raw parameter with no scheme, host, or allowlist check:

def _get_raw_request_object(self, request: OAuth2Request) -> str:
    if "request_uri" in request.payload.data:
        raw_request_object = self.get_request_object(
            request.payload.data["request_uri"]
        )
        if not raw_request_object:
            raise InvalidRequestUriError(state=request.payload.state)

get_request_object is abstract (line 213, raise NotImplementedError() at line 225), so authlib itself performs no outbound request. The defect is that authlib supplies unvalidated attacker input to that extension point and then documents the insecure implementation twice — in the class docstring (lines 34-38) and in the hook's own docstring (lines 218-223):

def get_request_object(self, request_uri: str):
    try:
        return requests.get(request_uri).text
    except requests.Exception:
        return None

Two points sharpen this beyond a generic documentation issue:

  • The allowlist already exists and is ignored. Authlib validates request_uris as client metadata (authlib/oauth2/rfc7591/claims.py:319) and require_request_uri_registration as server metadata (authlib/oauth2/rfc8414/models.py:263). The rfc9101 package contains zero references to either name, so the pre-registration model is never enforced at the point of use.
  • RFC 9101 §10.4.1 asks for controls that are absent. It states the server should "a) check that the value of the request_uri parameter does not point to an unexpected location, b) check that the media type of the response is application/oauth-authz-req+jwt, c) implement a timeout for obtaining the content of request_uri, and d) not perform recursive GET on the request_uri." The extension implements none of these and the documented example implements none of them either.

The two failure paths are distinguishable, which supplies the inference channel for a blind SSRF: a falsy fetch result raises InvalidRequestUriError (invalid_request_uri, lines 162-163), while a successful fetch of non-JWT content raises InvalidRequestObjectError (invalid_request_object, line 186).

PoC

This demonstrates the library-level defect with no network egress required: it shows the unvalidated URI reaching the fetch hook pre-authentication.

python -m venv .venv && .venv/bin/pip install authlib
from authlib.oauth2.rfc6749.requests import BasicOAuth2Payload, OAuth2Request
from authlib.oauth2.rfc9101 import JWTAuthenticationRequest

reached = []


class Extension(JWTAuthenticationRequest):
    def get_request_object(self, request_uri):
        reached.append(request_uri)  # the docstring puts requests.get(request_uri) here
        return None

    def resolve_client_public_key(self, client):
        return {"keys": []}
…
Record
GHSA-x4rv-c3wx-4cr8
CVSS 3.1
5.4 MediumCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:L/A:N
Weakness
CWE-918
Updated
2026-11-02
OSVPYSEC-2026-4360 5.4

Authlib is a Python library which builds OAuth and OpenID Connect servers. Prior to 1.9.0, Authlib's RFC 9101 JWTAuthenticationRequest passes the unauthenticated, client-controlled request_uri parameter to the abstract get_request_object() hook before applying a destination or registration policy; the hook itself performs no network request, while the documentation demonstrates an unrestricted HTTP fetch. In deployments whose integrator implements that hook as an unrestricted outbound fetch, a remote attacker who knows a valid public client identifier can make the authorization server request internal, link-local, or otherwise unintended URLs and can distinguish fetch outcomes through different error responses and timing. Deployments whose custom hook already applies a secure allowlist, destination controls, and retrieval limits are not affected. The JWTAuthenticationRequest implementation in authlib/oauth2/rfc9101/authorization_server.py forwards request_uri to get_request_object() before an application-approved retrieval policy accepts the destination. This issue is fixed in version 1.9.0.

Record
PYSEC-2026-4360
CVSS 3.1
5.4 MediumCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:L/A:N
Updated
2026-11-02
OSVUBUNTU-CVE-2026-114620 5.4

Authlib is a Python library which builds OAuth and OpenID Connect servers. Prior to 1.9.0, Authlib's RFC 9101 JWTAuthenticationRequest passes the unauthenticated, client-controlled request_uri parameter to the abstract get_request_object() hook before applying a destination or registration policy; the hook itself performs no network request, while the documentation demonstrates an unrestricted HTTP fetch. In deployments whose integrator implements that hook as an unrestricted outbound fetch, a remote attacker who knows a valid public client identifier can make the authorization server request internal, link-local, or otherwise unintended URLs and can distinguish fetch outcomes through different error responses and timing. Deployments whose custom hook already applies a secure allowlist, destination controls, and retrieval limits are not affected. The JWTAuthenticationRequest implementation in authlib/oauth2/rfc9101/authorization_server.py forwards request_uri to get_request_object() before an application-approved retrieval policy accepts the destination. This issue is fixed in version 1.9.0.

Record
UBUNTU-CVE-2026-114620
CVSS 3.1
5.4 MediumCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:L/A:N
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
authlib
PyPI
1.6.0 up to 1.9.0
1.9.0
python-authlib
Debian:12
All versions, plus listed versions
1.2.0-11.2.0-1+deb12u11.2.0-1+deb12u21.2.1-11.3.0-1
Show 23 moreShow less
1.3.0-21.3.0-31.3.1-11.3.2-11.3.2-21.4.0-11.4.1-11.5.0-11.5.1-11.5.2-11.6.0-11.6.1-11.6.3-11.6.4-11.6.5-11.6.6-11.6.7-11.6.8-11.6.9-11.7.0-11.7.2-11.7.2-21.9.1-1
None known
python-authlib
Debian:13
All versions, plus listed versions
1.6.0-11.6.0-1+deb13u11.6.1-11.6.3-11.6.4-1
Show 9 moreShow less
1.6.5-11.6.6-11.6.7-11.6.8-11.6.9-11.7.0-11.7.2-11.7.2-21.9.1-1
None known
python-authlib
Debian:14
before 1.9.1-1, plus listed versions
1.6.0-11.6.1-11.6.3-11.6.4-11.6.5-1
Show 7 moreShow less
1.6.6-11.6.7-11.6.8-11.6.9-11.7.0-11.7.2-11.7.2-2
1.9.1-1
authlib
PyPI
1.6.0 up to 1.9.0, plus listed versions
1.6.11.6.101.6.111.6.121.6.2
Show 11 moreShow less
1.6.31.6.41.6.51.6.61.6.71.6.81.6.91.7.01.7.11.7.21.8.0
1.9.0
python-authlib
Ubuntu:Pro:22.04:LTS
All versions, plus listed versions
0.15.4-10.15.5-10.15.5-1ubuntu0.1~esm10.15.5-1ubuntu0.1~esm2
None known
python-authlib
Ubuntu:Pro:24.04:LTS
All versions, plus listed versions
1.2.1-11.3.0-11.3.0-1ubuntu0.1~esm11.3.0-1ubuntu0.1~esm2
None known
python-authlib
Ubuntu:26.10
All versions, plus listed versions
1.6.7-11.7.2-11.7.2-2
None known
python-authlib
Ubuntu:Pro:26.04:LTS
All versions, plus listed versions
1.6.0-11.6.5-11.6.6-11.6.7-11.6.7-1ubuntu0.1~esm1
None known

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-114620 is a medium vulnerability (CVSS 5.4) in Authlib, published October 22, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.39%, the 32nd percentile. Fixed in authlib 1.9.0.

References

Show 6 moreShow less
This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open