CVE-2026-114620
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.
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
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 Medium
CVSS: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 Medium
CVSS: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_urisas client metadata (authlib/oauth2/rfc7591/claims.py:319) andrequire_request_uri_registrationas server metadata (authlib/oauth2/rfc8414/models.py:263). Therfc9101package 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_uriparameter does not point to an unexpected location, b) check that the media type of the response isapplication/oauth-authz-req+jwt, c) implement a timeout for obtaining the content ofrequest_uri, and d) not perform recursive GET on therequest_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 Medium
CVSS: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 Medium
CVSS: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 Medium
CVSS: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 Medium
CVSS: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_urisas client metadata (authlib/oauth2/rfc7591/claims.py:319) andrequire_request_uri_registrationas server metadata (authlib/oauth2/rfc8414/models.py:263). Therfc9101package 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_uriparameter does not point to an unexpected location, b) check that the media type of the response isapplication/oauth-authz-req+jwt, c) implement a timeout for obtaining the content ofrequest_uri, and d) not perform recursive GET on therequest_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 Medium
CVSS: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 Medium
CVSS: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 Medium
CVSS: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
| Package | Affected | Fixed |
|---|---|---|
authlibPyPI |
1.6.0 up to 1.9.0 | 1.9.0 |
python-authlibDebian: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 less1.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-authlibDebian: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 less1.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-authlibDebian: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 less1.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 |
authlibPyPI |
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 less1.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-authlibUbuntu: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-authlibUbuntu: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-authlibUbuntu:26.10 |
All versions, plus listed versions 1.6.7-11.7.2-11.7.2-2 |
None known |
python-authlibUbuntu: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
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE 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
github.com/authlib/authlib/security/advisories/GHSA-x4rv-c3wx-4cr8
github.com/authlib/authlib/pull/949
github.com/authlib/authlib/commit/6563f6f7a8c2f71d2f85ee7511d72a4fbae3acc0
github.com/authlib/authlib/commit/891e3f10ae5989176211f8be35dcc7cd40aa92c6
github.com/authlib/authlib/releases/tag/v1.9.0
nvd.nist.gov/vuln/detail/CVE-2026-114620
Left out here: the rest of 2 source descriptions. The JSON record has them.