With oidcRPMetaDataOptionsRequirePKCE set to 2, the authorization endpoint issues a code even when the request carries no code_challenge, and token() admits the exchange as long as a challenge was stored or an authentication method was returned for the caller. checkEndPointAuthenticationCredentials() skips the secret comparison for a Relying Party marked public and still returns the method deduced from the request, so any Basic or form credential satisfies the secret branch. validatePKCEChallenge() then passes, because neither a challenge nor a verifier is present.
An attacker who intercepts an authorization code issued to a public Relying Party can exchange it for the user's access, ID and refresh tokens by replaying the client_id with an arbitrary secret, which is the attack PKCE prevents. Dynamic client registration creates every Relying Party in this mode.
Analysis and contextual insights are available on OpenCVE Cloud.
Vendor Solution
Upgrade to Lemonldap-NG-Portal 2.23.4 or later.
Vendor Workaround
For deployments that cannot upgrade to 2.23.4, set RequirePKCE to 1 on public Relying Parties so that a code challenge is always required. Relying Parties created through dynamic registration are always in "PKCE or secret" mode, so that endpoint has to be disabled as well.
Tracking
Sign in to view the affected projects.
No advisories yet.
Fri, 25 Sep 2026 01:00:00 +0000
| Type | Values Removed | Values Added |
|---|---|---|
| Description | Lemonldap::NG::Portal versions from 2.23.0 before 2.23.4 for Perl allow a PKCE bypass for public Relying Parties in "PKCE or secret" mode because checkEndPointAuthenticationCredentials does not verify the client secret. With oidcRPMetaDataOptionsRequirePKCE set to 2, the authorization endpoint issues a code even when the request carries no code_challenge, and token() admits the exchange as long as a challenge was stored or an authentication method was returned for the caller. checkEndPointAuthenticationCredentials() skips the secret comparison for a Relying Party marked public and still returns the method deduced from the request, so any Basic or form credential satisfies the secret branch. validatePKCEChallenge() then passes, because neither a challenge nor a verifier is present. An attacker who intercepts an authorization code issued to a public Relying Party can exchange it for the user's access, ID and refresh tokens by replaying the client_id with an arbitrary secret, which is the attack PKCE prevents. Dynamic client registration creates every Relying Party in this mode. | |
| Title | Lemonldap::NG::Portal versions from 2.23.0 before 2.23.4 for Perl allow a PKCE bypass for public Relying Parties in "PKCE or secret" mode because checkEndPointAuthenticationCredentials does not verify the client secret | |
| Weaknesses | CWE-1390 | |
| References |
|
Subscriptions
No data.
Status: PUBLISHED
Assigner: CPANSec
Published:
Updated: 2026-09-25T02:10:01.838Z
Reserved: 2026-09-15T23:43:48.309Z
Link: CVE-2026-92289
No data.
Status : Received
Published: 2026-09-25T01:16:48.943
Modified: 2026-09-25T01:16:48.943
Link: CVE-2026-92289
No data.
OpenCVE Enrichment
No data.
-
CWE-1390
Weak Authentication