Skip to content
Heist/ feed
Back to feed
Critical

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

Type: advisorySources: OSV

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.

Products
Not specified
Affected versions
Not specified
Fixed versions
Not specified
CVEs
CVE-2026-92289
Confirmed fixed CVEs
Not specified
Updated in this feed
4 Nov 2026, 15:51 UTC · Revision 1

Source evidence

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

core-osv · Original source

Published 25 Sept 2026, 00:15 UTC

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.

osv:CVE-2026-92289
Complete source record
{
  "id": "dc6033d8455aa879be5c08cf058f6263a02147ff44205c3f9d806780bfdadb64",
  "url": "https://osv.dev/vulnerability/CVE-2026-92289",
  "method": "structured",
  "payload": {
    "kind": "advisory",
    "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",
    "summary": "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.",
    "evidence": "osv:CVE-2026-92289",
    "products": [],
    "severity": "critical",
    "structured": {
      "id": "CVE-2026-92289",
      "aliases": [
        "CVE-2026-92289"
      ],
      "metrics": [
        {
          "type": "CVSS_V3",
          "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N"
        }
      ],
      "affected": [
        {
          "ranges": [
            {
              "repo": "https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng",
              "type": "GIT",
              "events": [
                {
                  "introduced": "b33d2e2346596048fb83d4d98bb758b4e1b8e07d"
                },
                {
                  "fixed": "6602ae87a262e28539d54454ec99622c75141cb5"
                }
              ],
              "database_specific": {
                "extracted_events": [
                  {
                    "range": [
                      {
                        "introduced": "2.23.0"
                      },
                      {
                        "fixed": "2.23.4"
                      }
                    ],
                    "source": "AFFECTED_FIELD",
                    "strategy": "StandardRange"
                  },
                  {
                    "range": [
                      {
                        "introduced": "2.23.0"
                      },
                      {
                        "fixed": "2.23.4"
                      }
                    ],
                    "source": "DESCRIPTION"
                  }
                ]
              }
            }
          ],
          "versions": [
            "v2.23.3",
            "v2.23.2",
            "v2.23.1",
            "v2.23.0"
          ],
          "database_specific": {
            "source": "https://storage.googleapis.com/cve-osv-conversion/osv-output/CVE-2026-92289.json"
          }
        }
      ],
      "modified": "2026-10-28T02:30:36.798155008Z",
      "provider": "osv",
      "references": [
        "https://cpan.org/modules",
        "https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/92xxx/CVE-2026-92289.json",
        "https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/releases/v2.23.4",
        "https://nvd.nist.gov/vuln/detail/CVE-2026-92289",
        "https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/work_items/3719",
        "https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng"
      ],
      "provider_metadata": {
        "cwe_ids": [
          "CWE-1390"
        ],
        "cna_assigner": "CPANSec",
        "osv_generated_from": "https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/92xxx/CVE-2026-92289.json"
      }
    },
    "related_cves": [
      {
        "value": "CVE-2026-92289",
        "evidence": "/id"
      }
    ],
    "security_relevant": true,
    "severity_evidence": "/severity/0/score"
  },
  "source_id": "core-osv",
  "document_id": 504304,
  "published_at": "2026-09-25T00:15:49.826+00:00"
}