chore(deps): update dependency authlib to v1.9.1 [security] - autoclosed #74
Loading…
Reference in a new issue
No description provided.
Delete branch "renovate/pypi-authlib-vulnerability"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
This PR contains the following updates:
1.7.2→1.9.1Authlib: is_secure_transport() loopback exemption can be bypassed with a userinfo component, allowing cleartext-HTTP URLs to non-loopback hosts
CVE-2026-114614 / GHSA-jj7h-c3hg-m23x / PYSEC-2026-4354
More information
Details
Summary
authlib.common.security.is_secure_transport()is used throughout Authlib to enforce the OAuth 2.0 / OIDC requirement that endpoint and redirect URIs use TLS, with an RFC 8252 §7.3 exemption for loopbackhttp://URIs. The check is implemented as a textualstr.startswithprefix match, so a URL such ashttp://localhost:80@evil.example/cb— whose actual host isevil.exampleand whose scheme is plainhttp— is accepted as "secure". An attacker who can supply a URL to any of the sinks that rely on this check (OIDC RP-Initiated Logout dynamic client registration, RFC 8414 authorization-server metadata validation, error-redirect rendering) can smuggle a cleartext non-loopback URL past the TLS-required guard. This is a defense-in-depth / spec-conformance failure; severity is low.Details
Affected versions:
authlib >= 0.13, <= 1.7.2(all releases containing the loopback prefix exemption; verified against 1.7.2, the current latest)The vulnerable function, from
authlib/common/security.pyat v1.7.2:Per RFC 3986 §3.2 the authority component of a URI is
[ userinfo "@" ] host [ ":" port ]. The URLhttp://localhost:80@evil.example/cbtherefore has userinfolocalhost:80and hostevil.example. Because the check is a raw prefix match against the full URL string, thehttp://localhost:prefix matches the userinfo portion and the function returnsTrueeven though the scheme ishttpand the host is an arbitrary external name. The trailing:in each allow-list entry — presumably intended to force ahost:portshape and rejecthttp://localhost.evil.com— is also satisfied by theuser:passwordseparator inside userinfo, sohttp://localhost:@evil.example/matches too. The same construction works against all three loopback prefixes (http://127.0.0.1:...@evil.example/,http://[::1]:...@evil.example/).is_secure_transport()is consumed at the following locations in v1.7.2, none of which independently reject URLs containing a userinfo component:authlib/oidc/rpinitiated/registration.py:50-57— validation ofpost_logout_redirect_urisduring OIDC dynamic client registration for public clients (token_endpoint_auth_method == "none"). The precedingis_valid_url()check (authlib/common/urls.py:142-146) only requiresparsed.scheme and parsed.hostnameand does not reject userinfo, so the crafted URL passes both guards. A public client can therefore registerhttp://localhost:80@attacker.example/cbas a post-logout redirect target; the OpenID Provider will later 302 the end-user's browser to that cleartext non-loopback URL (carryingstate).authlib/oauth2/rfc8414/models.py:61,75,100,115,123,248,284— validation ofissuer,authorization_endpoint,token_endpoint,jwks_uri,registration_endpoint,revocation_endpoint,introspection_endpointin Authorization Server Metadata / OIDC Discovery documents. A relying party usingAuthorizationServerMetadata.validate()would accept endpoint values of this form as satisfying the "MUST use https" requirement when they do not.authlib/oidc/rpinitiated/discovery.py:12— validation ofend_session_endpointin provider metadata.authlib/oauth2/rfc6749/errors.py:64andauthlib/oauth1/rfc5849/errors.py:33— governs howredirect_uriis rendered in error bodies (cosmetic).The
http://localhost:prefix was introduced in commit0225c86b(first released in v0.13);http://127.0.0.1:andhttp://[::1]:were added later in the 1.6.x line. All variants share the same prefix-match weakness.PoC
Against the current latest release (1.7.2):
poc.py:Expected output:
Impact
Deployments are affected if they rely on
is_secure_transport()— directly or via the Authlib call sites listed above — to reject cleartext non-loopback URLs supplied by an external party. The most realistic path is an OpenID Provider that enables OIDC dynamic client registration and RP-Initiated Logout: a public client can register apost_logout_redirect_urisentry of the formhttp://localhost:80@attacker.example/…, which the provider will later use as an open-redirect target over plain HTTP. Relying parties that callAuthorizationServerMetadata.validate()on fetched discovery documents are also affected, though exploiting that sink requires the attacker to influence the metadata document. This does not bypass the OAuth 2.0 redirect-URI exact-match registration check and does not by itself yield authentication bypass or token theft; it defeats a TLS-required hardening check.Suggested fix: Parse the URI with
urllib.parse.urlsplit()and returnTrueonly ifscheme == "https", orscheme == "http"andhostname in {"localhost", "127.0.0.1", "::1"}; additionally reject any URI whose parsedusername/passwordis non-empty at these validation sites.Severity
CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:U/C:L/I:N/A:NReferences
This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).
CVE-2026-114614 / GHSA-jj7h-c3hg-m23x / PYSEC-2026-4354
More information
Details
Authlib is a Python library which builds OAuth and OpenID Connect servers. From 0.13 until 1.8.0, authlib.common.security.is_secure_transport() uses a textual prefix comparison for loopback HTTP exemptions, so a URL whose userinfo begins with a loopback host can be accepted even when its parsed host is an external non-loopback system. An external party able to supply a URL to OIDC RP-Initiated Logout registration, authorization-server metadata validation, or another call site can bypass the TLS-required guard and cause cleartext redirection or acceptance of cleartext endpoints. The issue does not bypass redirect URI exact matching and does not by itself forge tokens or authenticate users. The vulnerable authlib.common.security.is_secure_transport() implementation in authlib/common/security.py misinterprets the userinfo component before OIDC RP-Initiated Logout dynamic client registration and other consumers enforce transport security. This issue is fixed in version 1.8.0.
Severity
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:L/I:N/A:NReferences
This data is provided by OSV and the PyPI Advisory Database (CC-BY 4.0).
Authlib: empty signatures validation in JWS JSON deserialization
CVE-2026-96760 / GHSA-6v38-4h7w-rj9h
More information
Details
Authlib (prior to 1.9.0) contains a signature verification bypass vulnerability. The JsonWebSignature.deserialize_json() method accepts a JSON Serialization JWS object and returns the payload as successfully verified without checking for a signature and without requiring a cryptographic key.
Root cause
authlib/jose/rfc7515/jws.py, read on the installed 1.8.0 artifact:is_validis initialised toTrueand only ever set toFalsefrom inside the loop. A JWS JSONSerialization object whose
signaturesarray is empty iterates zero times, so the flag survives andthe payload is returned as successfully verified. No key is consulted, because no signature is
examined.
Reproduction
Observed on authlib 1.8.0, Python 3.14, clean virtualenv:
[C] proves the verifier works normally on a genuine object, so a deployment looks healthy. [D] proves
tampering is caught. [E] proves this is specifically the empty-array case and not a general
missing-member bug. [A] and [B] are the bypass, and [B] shows that holding the correct key does not
save a caller: the empty array is accepted either way.
For comparison, joserfc 1.7.5, the library this module's deprecation warning points users to, rejects
the identical object with
BadSignatureError. The correct behaviour already exists in your newerlibrary.
Impact
Any relying party that calls
JsonWebSignature.deserialize_json()on input it did not produce willaccept an attacker-authored payload as signed. Where that payload carries identity or authorisation
claims, this is a complete authentication bypass by an unauthenticated remote caller with no key
material.
What would fix it
In
_deserialize_json, reject an emptysignaturesarray before the loop, or initialise the flagfrom the signature count, for example
is_valid = len(obj["signatures"]) > 0. Pull request #938proposes the same thing.
Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:NReferences
This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).
Authlib incomplete algorithm-confusion fix permits HMAC forgery with prefixed public keys
CVE-2026-114615 / GHSA-7vr2-2fgp-9w7p / PYSEC-2026-4355
More information
Details
Summary
OctKey.import_key()carries the only guard that stops an asymmetric public key from being used as anHMAC secret in
authlib.jose. That guard israw_key.startswith(POSSIBLE_UNSAFE_KEYS)— anchored atbyte 0 — while the loader that consumes the identical bytes on the asymmetric path
(
cryptography.hazmat.primitives.serialization.load_pem_public_key/load_pem_x509_certificate)skips anything before the
-----BEGINline. A PEM public key or X.509 certificate carrying oneleading byte — a newline, a space, four spaces of indentation, a UTF-8 BOM, or a comment line — is
therefore not recognised, falls through, and becomes the HMAC secret. An attacker holding only the
issuer's public key then mints an
HS256token with arbitrary claims thatjwt.decode()accepts asauthentic.
This is an incomplete fix of CVE-2024-37568 / GHSA-5357-c2jx-v7qh. That advisory's fix is exactly
this guard (
git log -S 'POSSIBLE_UNSAFE_KEYS' -- authlib/jose/rfc7518/oct_key.pyreturns a singlecommit,
3bea812"fix: prevent OctKey to import ssh/rsa/pem keys", referencing issue #654), and theoriginal attack works again unchanged whenever the stored PEM does not start at offset 0.
Reproduced end-to-end on 1.8.0, the newest release (published 2026-08-30), and on
origin/main(
c529a61), withcryptography50.0.2.Preconditions
Both are deployment properties; neither is attacker-controlled at request time, and the attacker needs
no secret and no user interaction.
The relying party uses the documented module-level
jwtobject.from authlib.jose import jwtis built at
authlib/jose/__init__.py:55-72with the full list["HS256","HS384","HS512","RS256",...,"EdDSA"], andJsonWebToken.decode(
authlib/jose/rfc7519/jwt.py:80) exposes noalgorithmsparameter, so a caller of thedocumented object has no way to narrow it. This is the first code sample in
docs/jose/jwt.rst:21-31.This hazard is already documented:
docs/jose/jwt.rst:73-79says"This decoding method is insecure. By default
jwt.decodeparses the alg header. This allowssymmetric macs and asymmetric signatures.", and
docs/jose/jwt.rst:94-98says "You should nevercombine symmetric (HS) and asymmetric (RS, ES, PS) signature schemes." The point of this report is
not that the mixed list exists — it is that the
oct_key.py:81backstop shipped for preciselythat documented hazard does not hold.
The verification key is passed as PEM/certificate text whose bytes do not begin at offset 0 with
-----BEGIN. Each of the following forms was confirmed to forge, and each also still verifies agenuine RS256/ES256 token with the identical bytes, so nothing in the deployment looks broken:
CERTIFICATEPEM instead of aPUBLIC KEYPEMA raw DER SPKI blob also bypasses the guard, but DER cannot be used for genuine asymmetric
verification through this path, so I exclude it as a non-deployable configuration and mention it
only as further evidence of the recogniser/loader gap.
Details
authlib/jose/rfc7518/oct_key.py:10-17authlib/jose/rfc7518/oct_key.py:78-84bytes.startswithis anchored. The loader on the asymmetric path is not:authlib/jose/rfc7517/_cryptography_key.py:22-29callsload_pem_public_key/load_pem_x509_certificate, both of which scan forward for the armour header. So the set of bytestrings the recogniser rejects is strictly smaller than the set the loader accepts, and the difference
is exploitable.
Reach, for a caller of the documented object:
authlib/jose/rfc7518/jws_algs.py:59—HMACAlgorithm.prepare_key(raw_data)returnsOctKey.import_key(raw_data); this is the whole of the HMAC key handling.authlib/jose/rfc7519/jwt.py:80—JsonWebToken.decode(self, s, key, claims_cls=None, claims_options=None, claims_params=None); the algorithm comes from the token header and is checkedonly against the instance's list.
authlib/jose/__init__.py:55-72— that list contains both HS* and RS*/ES*/PS*/EdDSA.So
oct_key.py:81is the only thing between a mixed allow-list and using the public key as an HMACsecret, and it is bypassed by a single leading byte.
PoC
poc-authlib-e2e-http.pystands up a Flask API whose only authentication is the documentedjwt.decode(token, PUBLIC_KEY), wherePUBLIC_KEYis the issuer's RSA public key embedded as atriple-quoted Python literal (hence one leading newline). The attacker is given only that public
key.
The three controls establish that the guard does work on a canonical PEM (so the leading byte is
load-bearing), that ordinary signature verification is intact, and that pinning the algorithm is an
effective mitigation.
Per-form matrix, both key types, with a control proving genuine asymmetric verification still succeeds
on the exact same bytes:
Steps to reproduce
pip install authlib==1.8.0 cryptography flask requests(or indent it, or prepend a BOM or a comment line).
authlib.jose.rfc7518.oct_key.POSSIBLE_UNSAFE_KEYSdoes not match those bytes withstartswith, whilecryptography.hazmat.primitives.serialization.load_pem_public_keyloads them.from authlib.jose import jwtthentok = jwt.encode({"alg":"HS256"}, {"sub":"attacker","role":"admin"}, mutated_pem)jwt.decode(tok, mutated_pem)— verification succeeds and the claims are returned.Impact
Cryptographic signature-verification bypass leading to authentication bypass (CWE-347, algorithm
confusion). An unauthenticated attacker who knows only the issuer's public verification key — public by
definition, normally served at
/.well-known/jwks.jsonor in IdP metadata — forges tokens witharbitrary claims, including administrative roles and arbitrary subjects. In the PoC this yields an HTTP
200 and the application's admin secrets for
sub=attacker.Authlib had 103,356,930 PyPI downloads in the last month (pypistats
/api/packages/authlib/recent,read 2026-10-01), which is why I am reporting a bypass of a guard rather than only the documented
footgun it backstops.
Two notes for triage, in the interest of completeness:
authlib.joseemitsAuthlibDeprecationWarning("please use joserfc instead. It will be compatiblebefore version 2.0.0"). It is deprecated but still shipped, still documented in
docs/jose/jwt.rst,and still carries the download volume above.
ktyin thedata model, so
jwt.decodewith anRSAKey/ECKeyandalg=HS256raisesInvalidKeyTypeErrorforevery one of the seven loader-accepted forms. Typing the key rather than inspecting its bytes is what
makes the class unrepresentable there.
Suggested remediation
Either of these closes the class rather than one more byte form:
load_pem_public_key/load_pem_x509_certificate/load_ssh_public_key/load_der_public_keyon the candidate andreject it as an
octkey if any of them succeeds. This is the approach that makes joserfc immune andit cannot drift out of step with the loader, because it is the loader.
(
any(m in raw_key for m in POSSIBLE_UNSAFE_KEYS)) and add the-----BEGIN CERTIFICATE-----andDER
SubjectPublicKeyInfocases. This is strictly weaker than (1): the recogniser can drift againthe next time
cryptographybecomes more tolerant.Separately, and independent of this report: giving
JsonWebToken.decodeanalgorithms=parameterwould let callers of the documented module-level object apply the mitigation the docs recommend without
constructing a second
JsonWebToken.Credit
Found by zer0d4y5. Happy to test a patch branch before release.
Severity
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:NReferences
This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).
Authlib: ID token can disable its own nonce validation via the nonce_supported claim
CVE-2026-114617 / GHSA-c5mf-xmp2-59rc / PYSEC-2026-4357
More information
Details
Summary
OpenIDMixin.parse_id_token()reads thenonce_supportedclaim from the ID token it is validating. When that claim is booleanfalse, the expected nonce is set toNoneand nonce validation is skipped for that token.An ID token that carries this claim is therefore accepted in a session whose nonce does not match. A captured, validly signed ID token belonging to a victim can be replayed into an attacker-controlled session, authenticating the attacker as the victim at the relying party.
The code is identical in
authlib/integrations/base_client/sync_openid.py:82-83andauthlib/integrations/base_client/async_openid.py:84-85, so all framework integrations are affected. Fixed versions: none; reproduced on 1.8.0 (commit c529a61a).Preconditions: the ID token must carry a valid signature and pass
issandaudvalidation, and the attacker must be able to supply it toparse_id_token(). Authorization code flow is not affected. Implicit and hybrid relying parties, and applications callingparse_id_token()directly, are affected.Details
Affected code
authlib/integrations/base_client/sync_openid.py:80-85, inparse_id_token():authlib/integrations/base_client/async_openid.py:82-86contains the same code.Source of the claim
claimsis constructed fromtoken.claims, which is the decoded payload of the ID token passed toparse_id_token():claims.get("nonce_supported")therefore resolves against the ID token payload. It is not read fromload_server_metadata(), from client configuration, or from any other source under the relying party's control.Effect on validation
IDToken.validate_nonce()atauthlib/oidc/core/claims.py:69-83performs the comparison only when the expected value is truthy:Assigning
claims.params["nonce"] = Nonemakesnonce_valuefalsy, so both the presence check and the equality check are skipped. No error is raised andclaims.validate()completes normally.The docstring of that same method states the requirement:
Trigger condition
The comparison is
is False, so only a JSON booleanfalseactivates the branch. A string value"false"does not, and nonce validation proceeds normally in that case.Origin
The branch was added in commit
3ca7333c("Skip verifying nonce for Apple case") to accommodate a provider that emits anonce_supportedclaim, as referenced by the inline comment pointing to issue #259.Remediation
Read the flag from server metadata or client configuration rather than from the token:
This preserves the behavior for relying parties configured against a provider that does not support nonces, while preventing the token from determining whether it is subject to nonce validation.
Proof of concept
Environment
c529a61a(tagv1.8.0)Configuration
The relying party is a subclass of the shipped
OpenIDMixinsupplying onlyclient_idandload_server_metadata().fetch_jwk_set()returnsmetadata["jwks"]directly when the key set is present in metadata, so no HTTP request is made and no part of the validation path is stubbed.The signing key is a generated RSA key. All three tokens are signed with it, carry
issandaudmatching the relying party configuration, and are within their validity window. The relying party's session nonce isnonce-the-rp-actually-generated; every token carries the different noncenonce-from-the-captured-token.poc.py
Expected result
All three cases carry a nonce that does not match the relying party's session nonce, so all three should be rejected.
Observed result
Case [1] shows nonce validation rejecting a mismatched nonce under normal conditions. Case [2] differs from case [1] only by the addition of the
nonce_supportedclaim and is accepted, returning the subject of the replayed token. Case [3] confirms the branch requires a JSON boolean.The script exits 0 and produces identical output across three runs.
Impact
Type of vulnerability
Reliance on an untrusted input in a security decision (CWE-807), resulting in authentication bypass by capture-replay (CWE-294).
The nonce binds an ID token to the browser session that requested it and is the control that prevents a token issued for one session being presented in another. Because the flag that governs this check is read from the token itself, the check can be disabled by the data it is applied to.
Who is impacted
OpenID Connect relying parties built on authlib's client integrations where an attacker can supply an ID token to
parse_id_token():parse_id_token()directly on externally supplied input.Both the synchronous and asynchronous integrations are affected, so Flask, Django and Starlette deployments are equally exposed.
Relying parties using plain authorization code flow are not impacted, as the ID token is retrieved from the token endpoint over TLS following a
statelookup and cannot be substituted by an attacker.Consequence
An attacker in possession of a victim's ID token replays it into their own session. Nonce validation is skipped,
parse_id_token()returns aUserInfofor the victim's subject, and the relying party establishes an authenticated session as the victim. This grants access to the victim's account at that relying party, including any data and actions available through it.The token must carry a valid signature and pass
issandaudvalidation, so the vulnerability does not permit forging tokens or authenticating as an arbitrary subject. It removes the replay protection from a genuine token that has been captured, for example from browser history, aRefererheader, proxy or server logs, or a shared device.Mitigation available to integrators
None. The check is performed inside
parse_id_token(), and no parameter or configuration option is exposed to disable the behaviour or to override the nonce handling.Severity
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:NReferences
This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).
Authlib: Default JWT bearer grant accepts assertions for the wrong audience
CVE-2026-114618 / GHSA-fch4-3c6x-j4gc / PYSEC-2026-4358
More information
Details
Description
Summary
Authlib's default RFC 7523 JWT bearer grant leaves
get_audiences()empty, soverify_claims()only checks that anaudclaim exists instead of requiring it to match the current authorization server's token endpoint. An attacker holding a legitimately issued JWT assertion for any audience can present it to a different authorization server sharing the same signing key and obtain an access token.To be completely transparent, AI tools helped surface it. However, we have independently reproduced and carefully validated the issue. We follow responsible disclosure practices and are sharing this privately.
Affected Entrypoints
authlib.oauth2.rfc7523.JWTBearerGrant— defaultget_audiences()returns empty listauthlib.jose.jwt.decode()withclaims_optionsfor audience validationauthlib.integrations.flask_oauth2.ResourceProtector.validate_request()when audience checking is enabledExploit Path
Proof of Concept
Observed Result
access_tokenissued despiteaud: "https://evil.test/token"error: "invalid_grant"— correctly rejects mismatched audienceget_audiences()returns empty, so audience validation is effectively skippedImpact
get_audiences()Credit
Reported by a security research team from the University of Sydney, focusing on detecting open source software vulnerabilities.
Liyi Zhou: https://lzhou1110.github.io/
Ziyue Wang: https://zyy0530.github.io/
Strick: https://str1ckl4nd.github.io/
Maurice: https://maurice.busystar.org/
Chenchen Yu: https://7thparkk.github.io/
Severity
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:NReferences
This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).
Authlib: OpenID implicit grant checks raw scope instead of allowed scope before issuing ID tokens
CVE-2026-114619 / GHSA-q686-2qmg-hqc7 / PYSEC-2026-4359
More information
Details
Report metadata
authlib(PyPI,pkg:pypi/authlib)authlib.oidc.core.grants.implicit.OpenIDImplicitGrant.validate_authorization_requestc529a61af40e3efe05286140e00fbdced07d7987(v1.8.0). Earlier releases were not checked.OpenIDImplicitGrant, registered withserver.register_grant(...))OpenIDImplicitGrantis registered. Client metadata decides exposure: Authlib's standardClientMixinchecks response type and scope independently, so a client can be permittedid_tokenresponses without being allowed theopenidscope.Summary
OpenIDImplicitGrant.validate_authorization_request()first runs the parentImplicitGrantvalidation, which filters the requested scope throughclient.get_allowed_scope()and stores the result inrequest.scope. It then decides whether this is an OpenID request by checking the raw, client-suppliedrequest.payload.scopeinstead of that filtered value. A client that is allowedprofilebut notopenidcan therefore requestscope=openid profile, pass the check, and receive a signed ID token (withsuband profile claims) once the user consents. This happens even when Authlib's built-in, scope-filteringBearerTokenGeneratoris in use.The tainted input is the authorization request's
scopeparameter. The OAuth client fully controls it, and the client is the very party the scope restriction is meant to constrain. Any registered client can addopenidto its request if it is permitted anid_tokenorid_token tokenresponse type and its allowed scopes excludeopenidbut include a claim-bearing scope such asprofile.Sibling paths treat the same client correctly, which suggests the raw-scope check is a bug rather than intended behaviour:
ImplicitGrant.validate_authorization_request()-> filters the requested scope throughclient.get_allowed_scope()intorequest.scope(safe,authlib/oauth2/rfc6749/grants/implicit.pylines 141-147)OpenIDImplicitGrant.validate_authorization_request()-> checks the rawrequest.payload.scope(unsafe,authlib/oidc/core/grants/implicit.pyline 72)UserInfoEndpoint-> rejects the same client's access token with 403insufficient_scope(safe; observed during verification, line not recorded)id_tokenfor the same client (safe; observed during verification, line not recorded)Impact
A registered OAuth client that the operator has excluded from the
openidscope can get an OpenID Connect ID token for any user who logs in and approves its authorization request. During verification the provider returned an RS256-signed ID token carryingiss,aud(the requesting client),nonce,auth_time,at_hash,subandname, while the granted scope was onlyprofile. A consent page built the way the Authlib docs show lists onlyprofile, so the user is not shown that an identity token will be issued.Without this bug, the same request fails with
InvalidScopeError("Missing 'openid' scope") because the client's resolved scope does not includeopenid. The new capability is the ID token itself: a signed assertion of the user's identity (sub) plus claims from the client's other allowed scopes. Gating that token is exactly what theopenidscope is for. The access token stays restricted when the built-in token generator is used: Authlib'sUserInfoEndpointrejects it with 403insufficient_scope.Scoring note: we did not compute a CVSS score. An initial triage rated this High. After dynamic verification we assess practical severity as closer to Medium, because:
id_tokenresponse types.audis the attacking client.Two kinds of deployment are not affected:
id_tokenorid_token tokenresponse type is also allowed theopenidscope.Preconditions
OpenIDImplicitGrant(or a subclass), e.g.server.register_grant(MyOpenIDImplicitGrant). The vulnerable method runs on every OIDC implicit authorization request.id_tokenorid_token token). Nothing in Authlib ties this to theopenidscope. The standard SQLAlchemyClientMixinchecks response type and scope independently, and it filters requested scopes against the client's allowed scopes atauthlib/integrations/sqla_oauth2/client_mixin.py:124-129.openidbut include another claim-bearing scope, such asprofile.openidto otherwise allowed scopes (e.g.scope=openid profile), with anonce.request.payload.scopecontainsopenidwhile the filteredrequest.scopedoes not. Sois_openid_scope(self.request.payload.scope)is true atimplicit.py:72and noInvalidScopeErroris raised.No non-standard usage, monkey-patching or unusual configuration is needed: this is the public grant used as intended. Keeping a client's response types and allowed scopes in sync is not documented as the integrator's responsibility. The parent grant stores the filtered
request.scopespecifically so that authorization decisions use it. We did not capture a link to the relevant Authlib docs page, but the verification built its consent page the way those docs show.Data flow
scopeparameter, e.g.GET /authorize?response_type=id_token%20token&client_id=c&redirect_uri=https%3A%2F%2Fc%2Fcb&scope=openid%20profile&nonce=n. The raw value remains available asrequest.payload.scope.ImplicitGrant.validate_authorization_request()filters the requested scope throughclient.get_allowed_scope()and stores the result inrequest.scope(here'profile').request.payload.scopestill holds the rawopenid profile(authlib/oauth2/rfc6749/grants/implicit.py:141-147).OpenIDImplicitGrant.validate_authorization_request()uses the raw value to decide whether this is an OpenID request:if not is_openid_scope(self.request.payload.scope):(authlib/oidc/core/grants/implicit.py:72). The injectedopenidsatisfies the check, so the method returns the redirect URI instead of raisingInvalidScopeError(authlib/oidc/core/grants/implicit.py:70-84).OpenIDImplicitGrantis the public grant that serves OIDC implicit authorization requests. After the user consents,create_granted_params()andprocess_implicit_token()issue the ID token and user claims (authlib/oidc/core/grants/implicit.py:112-129,authlib/oidc/core/grants/implicit.py:132-169).Vulnerable code
authlib/oidc/core/grants/implicit.py, lines 70-84 atc529a61af40e3efe05286140e00fbdced07d7987(an excerpt;...marks code left out of the captured snippet):Reproduction
Verified two ways on Authlib
c529a61af40e3efe05286140e00fbdced07d7987(v1.8.0):curlThe Python and Flask versions were not recorded.
Setup: a client registered with
scope='profile'only (noopenid) and response typesid_token/id_token token. It uses Authlib's built-in SQLAlchemyClientMixinand the built-in scope-filteringBearerTokenGenerator.scope=openid profileand anonce.ImplicitGrantsetsrequest.scope='profile'. A consent page built the way the docs show displays onlyprofile.OpenIDImplicitGrant.validate_authorization_request()checks the rawrequest.payload.scopeat line 72, so the request passes.iss,aud(the client),nonce,auth_time,at_hash,subandname, while the granted scope isprofile. The ID token's signature verified against the provider's JWKS.Controls run during verification:
openidreturnsinvalid_scope("Missing 'openid' scope").UserInfoEndpointrejects this client's access token with 403insufficient_scope.id_token.The sketch below shows the request shape against Authlib's Flask OIDC test app. The verification's own test script is not included here.
InvalidScopeError/invalid_scope("Missing 'openid' scope"), because the client's resolved allowed scope (request.scope == 'profile') does not includeopenid.subandname) while the granted scope isprofile.Suggested remediation
Decide whether to issue OpenID tokens from the scope the grant actually authorized, never from the raw requested scope. The authorized scope is
self.request.scope, which the parent grant has already filtered throughclient.get_allowed_scope().During verification, this one-line change at line 72 blocked the exploit, and the existing OIDC implicit/hybrid tests still passed (23 passed).
The same rule should hold for the rest of OIDC issuance.
create_granted_params()(authlib/oidc/core/grants/implicit.py:112-129) passes the rawpayload.scopetogenerate_token. It should passself.request.scopeinstead.Notes:
create_granted_params()hands the rawpayload.scopetogenerate_token. So a deployment whose custom token generator does not filter scope also grants the client access-token scopes it is not allowed; verification notedopenidandemail. Authlib's built-inBearerTokenGeneratorre-filters the access-token scope, so this only shows up with a non-filtering generator. That re-filtering does not stop the ID token.create_granted_params(), we did not audit every scope read inprocess_implicit_token()(authlib/oidc/core/grants/implicit.py:132-169), or in other OIDC grants such as the hybrid grant. Whether they share the pattern is not verified.ImplicitGrantand inClientMixinUserInfoEndpoint, which rejects this client's access token with 403insufficient_scopeSuggested regression test, alongside the existing Flask OIDC implicit-grant tests:
scope='profile'andresponse_types=['id_token token'].scope=openid profileand anonce, and approve it.invalid_scopeerror ("Missing 'openid' scope") and that the redirect contains noid_token.A second case should use a token generator that does not filter scope, and assert that the issued access token carries only the client's allowed scopes.
Severity
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:L/I:L/A:NReferences
This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).
Authlib: Unvalidated request_uri fetch in JWT-secured authorization request (JAR) leading to SSRF
CVE-2026-114620 / GHSA-x4rv-c3wx-4cr8 / PYSEC-2026-4360
More information
Details
Summary
Authlib's RFC 9101 (JAR) extension passes the attacker-controlled
request_uriauthorization parameter straight to theget_request_object()fetch hook with no validation, at a pre-authentication endpoint. Authlib already defines the pre-registration allowlist for this (request_urisclient metadata andrequire_request_uri_registrationserver metadata) but the extension never consults it, and both docstrings instruct integrators to implement the hook as an unrestrictedrequests.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 fromauthlib/oauth2/rfc9101/authorization_server.py.The extension registers itself on the
before_get_authorization_granthook (lines 62-65), so it runs on every authorization request before any user or client authentication.support_request_uridefaults toTrue(line 58).The only gate before the sink is that
client_idnames an existing client (lines 91-103). Aclient_idis a public, non-secret identifier.The sink at line 159 forwards the raw parameter with no scheme, host, or allowlist check:
get_request_objectis 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):Two points sharpen this beyond a generic documentation issue:
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.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 raisesInvalidRequestObjectError(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.
Output on authlib 1.7.2:
Against a deployment that used the docstring implementation, the equivalent unauthenticated request is:
Returning a fetched-but-non-JWT body instead of
Nonein the snippet above yieldsInvalidRequestObjectErrorrather thanInvalidRequestUriError, showing the oracle that distinguishes a reachable target from an unreachable one.Impact
Server-side request forgery, reachable without authentication by anyone who knows a valid
client_id. In a deployment that implementedget_request_objectas documented, an attacker can make the authorization server issue GET requests to arbitrary URLs: internal-only services, cloud metadata endpoints such as169.254.169.254, and side-effectful internal GET routes. Theinvalid_request_uriversusinvalid_request_objectsplit, together with response timing, provides an oracle for internal host and port discovery. RFC 9101 §10.4.1 additionally notes the DoS and recursive-lookup risks that the missing timeout and recursion checks leave open.Response bodies are consumed as a JWT and never reflected, so this is a blind primitive rather than direct data exfiltration. Because the fetch executes in integrator code, deployments that already allowlist inside their override are unaffected — but authlib provides no hook to make that the default, ships
support_request_uri=True, and its documentation steers integrators to the unsafe implementation, so the insecure outcome is the expected one.Severity
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:L/A:NReferences
This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).
CVE-2026-114615 / GHSA-7vr2-2fgp-9w7p / PYSEC-2026-4355
More information
Details
Authlib is a Python library which builds OAuth and OpenID Connect servers. From 1.3.1 until 1.9.0, OctKey.import_key() checks asymmetric-key markers only at byte zero while Authlib's PEM loaders accept leading whitespace, comments, or a byte-order mark. In deployments that use the documented mixed algorithm registry and already configure verification with PEM or certificate bytes containing such a prefix, an unauthenticated attacker who knows those same public-key bytes can use them as an HMAC secret and forge HS256 tokens with arbitrary identity or authorization claims. This is a bypass of the remediation for CVE-2024-37568. The module-level jwt object reaches OctKey.import_key() in authlib/jose/rfc7518/oct_key.py, where POSSIBLE_UNSAFE_KEYS fails to identify prefixed asymmetric key material. This issue is fixed in version 1.9.0.
Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:NReferences
This data is provided by OSV and the PyPI Advisory Database (CC-BY 4.0).
CVE-2026-114617 / GHSA-c5mf-xmp2-59rc / PYSEC-2026-4357
More information
Details
Authlib is a Python library which builds OAuth and OpenID Connect servers. Prior to 1.9.0, OpenIDMixin.parse_id_token() reads the nonce_supported decision from the untrusted ID token being validated and sets the expected nonce to null when that claim is the JSON boolean false. In implicit and hybrid relying parties, or applications that directly accept externally supplied ID tokens, an attacker with a captured validly signed token can bypass the nonce-to-session binding and replay the victim's token into an attacker-controlled session. Plain authorization code flow is not affected, and the token must still pass signature, issuer, and audience validation. OpenIDMixin.parse_id_token() trusts nonce_supported in both authlib/integrations/base_client/sync_openid.py and authlib/integrations/base_client/async_openid.py to disable the expected nonce. This issue is fixed in version 1.9.0.
Severity
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:NReferences
This data is provided by OSV and the PyPI Advisory Database (CC-BY 4.0).
CVE-2026-114618 / GHSA-fch4-3c6x-j4gc / PYSEC-2026-4358
More information
Details
Authlib is a Python library which builds OAuth and OpenID Connect servers. Prior to 1.9.0, the default RFC 7523 JWTBearerGrant.get_audiences() returns an empty list, causing JWTBearerGrant.verify_claims() to require only that an aud claim exists without matching the current authorization server. An attacker holding a legitimate assertion for another service can present it to a server that shares the signing key and uses the default grant, obtaining an access token across a trust boundary. Implementations that override get_audiences() with the server's valid audience identifiers are not affected. This issue is fixed in version 1.9.0.
Severity
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:NReferences
This data is provided by OSV and the PyPI Advisory Database (CC-BY 4.0).
CVE-2026-114619 / GHSA-q686-2qmg-hqc7 / PYSEC-2026-4359
More information
Details
Authlib is a Python library which builds OAuth and OpenID Connect servers. Prior to 1.9.0, OpenIDImplicitGrant.validate_authorization_request() checks the client-controlled raw request.payload.scope for openid after the parent grant has filtered allowed scopes into request.scope. A registered client permitted an ID token response type but not the openid scope can add openid to the request, obtain user consent, and receive a signed ID token containing the user's subject and allowed profile claims. Authorization code flow and deployments that allow openid for every client permitted an ID token response are not affected. In authlib/oidc/core/grants/implicit.py, OpenIDImplicitGrant.validate_authorization_request() checks request.payload.scope instead of the filtered request.scope. This issue is fixed in version 1.9.0.
Severity
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:L/I:L/A:NReferences
This data is provided by OSV and the PyPI Advisory Database (CC-BY 4.0).
CVE-2026-114620 / GHSA-x4rv-c3wx-4cr8 / PYSEC-2026-4360
More information
Details
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.
Severity
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:L/A:NReferences
This data is provided by OSV and the PyPI Advisory Database (CC-BY 4.0).
Authlib accepts an empty HMAC key, allowing JWS/JWT signature forgery (HS256/HS384/HS512)
CVE-2026-114616 / GHSA-8m4g-j4wp-wgcg / PYSEC-2026-4356
More information
Details
Reporter: Cavan Loughran, Celvex Group Inc.
Summary
Authlib's symmetric (oct) key handling accepts an empty key (empty bytes b'' / empty string '') as a valid HMAC signing and verification key. An empty HMAC key produces a deterministic digest that any party can reproduce, so an attacker who knows (or can cause) the application to verify a token with an empty key can forge arbitrary tokens that pass HS256/HS384/HS512 signature verification. This is the Authlib member of the cross-language empty-HMAC-key family already assigned CVE-2026-44351 (fast-jwt, npm) and CVE-2026-45363 (ruby-jwt, RubyGems).
This is DISTINCT from Authlib's existing recent JWT-verification advisories. It is not closed by CVE-2026-27962 / GHSA-wvwj-cvrp-7pv5 (JWS JWK header injection, the key=None case), nor by CVE-2026-28802 / GHSA-7wc2-qxgw-g8gg (alg:none blank-signature bypass), nor by GHSA-5357-c2jx-v7qh (algorithm confusion with asymmetric public keys). Those address header-driven key injection, the none algorithm, and asymmetric-vs-symmetric confusion respectively; none of them rejects a zero-length oct key.
Affected versions
Authlib <= 1.7.2 (latest release 1.7.2, 2026-05-06). Confirmed present at the v1.7.2 release tag and on the current main HEAD. The affected code is in authlib/jose/rfc7518/oct_key.py and authlib/jose/rfc7518/jws_algs.py.
Root cause (exact code location, release tag v1.7.2)
return isinstance(key, bytes). An empty bytes object passes.if raw_key.startswith(POSSIBLE_UNSAFE_KEYS): raise ValueError(...), i.e. PEM/SSH prefixes). Empty bytes do not match any unsafe prefix, so b'' is accepted.return OctKey.import_key(raw_data).hmac.new(op_key, msg, self.hash_alg)/hmac.compare_digest(...). With an empty op key this becomes hmac.new(b'', ...): a deterministic, publicly reproducible digest. There is no empty-key or minimum-length check.Why this is a real signature bypass
An empty HMAC key makes the signature a public, deterministic function of the header and payload, so anyone can compute a valid signature and forge tokens. The realistic trigger matches the sibling CVEs: the deploying application sources the verification key from a place that can be empty at runtime, for example os.environ.get('JWT_SECRET', ''), a database/config column whose default is '', or a key-resolver that returns '' on a miss. Authlib is widely used to BUILD token verifiers (OAuth 2.0 resource servers, OIDC relying parties), and Authlib's own recent advisory history shows the JWS/JWT verify path is the live attack surface, so a key-resolution path that can yield '' is a realistic exposure.
Reproduction (prose, no weaponized exploit)
No live system was probed; the above describes the class. The vulnerable code path and the absent guard are confirmed by direct reading of the public source at the v1.7.2 tag and on current main.
Proof the fix is known-good (no novelty risk)
The same maintainer's newer JOSE library, joserfc, ALREADY rejects empty oct key material outright. In src/joserfc/_rfc7518/oct_key.py, import_key raises a ValueError on empty oct material, with an explicit note that an empty oct key produces a deterministic HMAC digest that any party can reproduce, allowing trivial signature forgery in JWS HS256/HS384/HS512 verification. (joserfc additionally warns on keys below 112 bits.) The same guard is simply absent from the older, far more widely deployed Authlib rfc7518 package. The flagship Python JOSE libraries also guard: PyJWT raises InvalidKeyError('HMAC key must not be empty.') for zero-length keys, and jwcrypto enforces an RFC 7518 minimum key length.
Impact
Token forgery / authentication bypass in OAuth 2.0 resource servers and OIDC relying parties built on Authlib whenever the HMAC verification key can be empty at runtime. An attacker can mint tokens with arbitrary claims (for example elevated scopes or another user's subject) that pass signature verification.
Suggested remediation
Reject empty oct key material in OctKey.import_key (and/or validate_raw_key), exactly as the maintainer's joserfc library already does, before the key can reach hmac.new in HMACAlgorithm.sign / verify. Consider also adopting joserfc's sub-112-bit minimum-length warning/rejection for HMAC keys.
Disclosure
Reporter: Cavan Loughran, Celvex Group Inc.
Severity
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:NReferences
This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).
Authlib RFC 7592 examples omit registration-access-token client binding
CVE-2026-116672 / GHSA-c73q-w75p-j82v
More information
Details
Description
Summary
RFC 7592 (OAuth 2.0 Dynamic Client Registration Management Protocol) lets a previously registered client read, update, or delete its own registration, authenticated by a
registration_access_tokenissued specifically to that client at registration time. The entire security model of this protocol depends on the server verifying that the token presented in the request actually belongs to the client identified in the request, not merely that the token is valid for some client.Authlib's
ClientConfigurationEndpointimplements the control flow correctly in structure, callingauthenticate_token, thenauthenticate_client, thencheck_permission, and treats all three as abstract methods that "Developers MUST implement in subclass." The problem is that the documented example implementations for these methods, taken together exactly as written, never perform the one check that matters: binding the authenticated token to the specific client being accessed. A developer who implements these methods by following the provided examples ends up with a complete authorization bypass on this endpoint.Details
authenticate_client's documented example (authlib/oauth2/rfc7592/endpoint.py):This looks the target client up purely by the
client_idsupplied in the request payload, with no reference to the token at all.check_permission's documented example, in the same file:This checks a property of the target client alone (whether it is generally "editable"), again with no reference to
request.credential, the authenticated token object returned earlier byauthenticate_tokenand stored on the request specifically so that later steps can check it:request.credentialis set specifically so that a binding check can be performed downstream, but neither documented example ever reads it. Following both examples as written produces an implementation where the only requirements to access, modify, or delete a client's registration are: possessing any valid registration_access_token for any client, and knowing or guessing the targetclient_id.This is meaningfully different from how the equivalent example is written for the token introspection endpoint (RFC 7662) elsewhere in the same codebase, which does correctly demonstrate checking the authenticated caller's own identity (
authlib/oauth2/rfc7662/introspection.py):In that endpoint,
clientrepresents the already-authenticated caller (verified through normal client credential authentication earlier in the flow), so checking a property ofclientis meaningful authorization logic. In the RFC 7592 endpoint,clientinstead represents the target being acted upon, not the caller, so the same style of example is actively misleading: it looks like a reasonable authorization check but performs none of the binding the protocol requires.No file anywhere in the repository, including the Flask, Django, and SQLAlchemy integration modules, provides a complete, corrected reference implementation of
ClientConfigurationEndpoint. The misleading docstring examples are the only guidance shipped for this endpoint.Realistic exploitability
RFC 7591 dynamic client registration is commonly deployed without requiring an initial access token, since the specification explicitly anticipates open, self-service registration as a normal deployment model. Under that common configuration, an attacker can freely self-register their own throwaway client with no authentication at all, receive a valid
registration_access_tokenscoped to that throwaway client, and then present that same token against/register/{target_client_id}for any other client, since neither documented example checks that the token corresponds to the target. If the target client'seditableproperty (or whatever equivalent the developer implements based on the documented example) is true, an attacker can read the victim client's full registration including its metadata, update it (for example, changingredirect_uristo an attacker-controlled endpoint, enabling authorization code or token interception against that client's users), or delete it outright.Reproduction
ClientConfigurationEndpointwithauthenticate_clientandcheck_permissionimplemented exactly as documented in the class's own docstrings.client_id_Aandregistration_access_token_A.client_id_B, belonging to a different, unrelated client.GET /register/client_id_B(orPUT/DELETE) withAuthorization: Bearer registration_access_token_A, andclient_idset toclient_id_Bin the request body for thePUTcase.authenticate_tokensucceeds becauseregistration_access_token_Ais a valid token.authenticate_clientsucceeds because it looks upclient_id_Bdirectly from the payload, ignoring which token was presented.check_permissionsucceeds because it only checksclient_B.editable, not whetherregistration_access_token_Ahas any relationship toclient_B. The request proceeds and returns, modifies, or deletes client B's registration.Impact
Full read, modify, and delete access to any other client's registration record, for any party able to obtain a valid registration_access_token for any client of their own. In an open dynamic registration deployment this reduces to no meaningful barrier at all, since attackers can self-issue their own qualifying token for free. Impact includes disclosure of client metadata, redirect URI hijacking enabling authorization code or token interception, and denial of service via deletion of arbitrary client registrations.
Suggested fix
Update the documented example for
check_permission(orauthenticate_client) to explicitly demonstrate binding the authenticated token to the target client, for example:and add an explicit warning in both docstrings that omitting this comparison results in a complete authorization bypass on this endpoint. Consider also shipping a complete, correct reference implementation of
ClientConfigurationEndpointin the Flask/Django/SQLAlchemy integration modules, since none currently exists.Affected products
Ecosystem: pip
Package name: Authlib
Affected versions: 1.7.2
Patched versions: 1.9.1
Severity
Privileges Required is Low, reflecting that the attacker needs some registration_access_token of their own, which under the common open dynamic registration deployment model is trivially self-issued. This is a documentation/reference-implementation issue rather than a bug the library enforces unconditionally on every deployment, since
authenticate_clientandcheck_permissionare abstract methods a developer must implement; the finding is that the only guidance provided for implementing them correctly is, itself, exploitable if followed as written.Severity
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:HReferences
This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).
CVE-2026-114616 / GHSA-8m4g-j4wp-wgcg / PYSEC-2026-4356
More information
Details
Authlib is a Python library which builds OAuth and OpenID Connect servers. Prior to 1.9.1, Authlib's OctKey.import_key() and HMAC signing and verification path accept zero-length key material. If an application's secret lookup can return an empty string or empty bytes, a remote attacker can compute the deterministic HS256, HS384, or HS512 signature for arbitrary token claims and have Authlib treat the token as authentic. This issue is fixed in version 1.9.1.
Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:NReferences
This data is provided by OSV and the PyPI Advisory Database (CC-BY 4.0).
Release Notes
authlib/authlib (authlib)
v1.9.1Compare Source
Changelog: https://docs.authlib.org/en/stable/upgrades/changelog.html#changelog-1-9-1
What's Changed
Full Changelog: https://github.com/authlib/authlib/compare/v1.9.0...v1.9.1
v1.9.0Compare Source
What's Changed
New Contributors
Full Changelog: https://github.com/authlib/authlib/compare/v1.8.0...v1.9.0
v1.8.0Compare Source
What's Changed
id_token_signed_response_algclient metadata to guess algs by @azmeuk in #888New Contributors
Full Changelog: https://github.com/authlib/authlib/compare/v1.7.2...v1.8.0
Configuration
📅 Schedule: (in timezone Europe/Paris)
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR has been generated by Mend Renovate CLI.
d1124b2352e173a743c9e173a743c964b6cdbf0864b6cdbf08adf725de63chore(deps): update dependency authlib to v1.9.1 [security]to chore(deps): update dependency authlib to v1.9.1 [security] - autoclosedPull request closed