CVE-2026-19349 Overview
CVE-2026-19349 is an authentication bypass vulnerability in LemonLDAP::NG Portal affecting the GitHub and LinkedIn OAuth2 authentication backends. The flaw allows unauthenticated attackers to obtain a valid Single Sign-On (SSO) session by replaying the OAuth2 state parameter as a session cookie. The vulnerability stems from an incorrect call to getApacheSession() in extractFormInfo(), which writes the OAuth2 state to global SSO session storage instead of a scoped state store. Deployments running the shipped bootstrap configuration with default => accept access rules are directly exposed. The issue is tracked under [CWE-305: Authentication Bypass by Primary Weakness].
Critical Impact
Unauthenticated network attackers can obtain valid SSO sessions on LemonLDAP::NG deployments using GitHub or LinkedIn authentication, gaining access to protected virtual hosts without credentials.
Affected Products
- Lemonldap::NG::Portal versions 2.0.0 through 2.16.8
- Lemonldap::NG::Portal versions 2.17.0 through 2.21.4
- Lemonldap::NG::Portal versions 2.22.0 through 2.23.2
Discovery Timeline
- 2026-08-16 - CVE-2026-19349 published to NVD
- 2026-08-17 - Last updated in NVD database
Technical Details for CVE-2026-19349
Vulnerability Analysis
The vulnerability resides in the OAuth2 state handling logic of the LemonLDAP::NG Portal GitHub and LinkedIn authentication backends. Before redirecting the visitor to the identity provider, the extractFormInfo() routine creates a state session used to correlate the eventual OAuth2 callback with the originating request. The state identifier is returned to the unauthenticated visitor as the state query parameter in the redirection URL.
Because the state identifier is treated by the backend session storage as a full SSO session identifier, any visitor reaching the GitHub or LinkedIn endpoint can lift the returned state value and present it as their portal session cookie. The resulting session contains no _user and no authenticationLevel, yet the shipped bootstrap configuration accepts it because its virtual host access rule defaults to default => accept. Deployments with rules that explicitly test the user identity or require an authentication level are less exposed but should still patch.
Root Cause
The root cause is a positional-versus-named argument confusion in the call getApacheSession( undef, 1, 0, 'GitHubState' ). The getApacheSession() function expects a session identifier followed by a named argument hash. The trailing positional arguments are consumed as hash pairs, so the kind parameter is never set and defaults to SSO. The state session is therefore persisted in global SSO session storage rather than an isolated state store, making its identifier interchangeable with a valid SSO session token.
Attack Vector
An attacker browses to the portal's GitHub or LinkedIn authentication endpoint, which triggers state creation and returns a redirect URL containing the state parameter. The attacker captures that value from their own browser and sets it as their portal session cookie. Subsequent requests to protected virtual hosts are evaluated against the SSO session, which passes the default => accept rule. No user interaction, credentials, or victim involvement is required.
The LemonLDAP::NG project describes the flaw and fix in the LemonLDAP-NG 2.16.9 release notes and the OpenWall OSS-Security discussion.
Detection Methods for CVE-2026-19349
Indicators of Compromise
- Portal session cookies whose identifier matches a previously issued OAuth2 state value in GitHub or LinkedIn redirect URLs.
- SSO sessions in the session backend lacking the _user and authenticationLevel attributes.
- Access log entries showing successful requests to protected virtual hosts from clients that never completed an OAuth2 callback.
Detection Strategies
- Audit the session backend (File, Redis, database) for sessions labelled GitHubState or LinkedInState stored under the SSO kind.
- Correlate portal /oauth2/github or /oauth2/linkedin requests with the state parameter values later observed as session cookies from the same or different source IPs.
- Alert on any authenticated request whose session record has empty _user or an authenticationLevel of 0.
Monitoring Recommendations
- Enable verbose portal logging to capture state creation events and match them against subsequent cookie usage.
- Forward LemonLDAP::NG portal and handler logs to a centralized SIEM for correlation across virtual hosts.
- Track failed OAuth2 callback completions paired with successful downstream resource access from the same session identifier.
How to Mitigate CVE-2026-19349
Immediate Actions Required
- Upgrade Lemonldap::NG::Portal to version 2.16.9, 2.21.5, or 2.23.3 depending on the deployed release branch.
- If GitHub or LinkedIn authentication is not required, disable those modules in the LemonLDAP::NG manager until patching is complete.
- Invalidate all active portal sessions after upgrading to purge any state-derived sessions minted during the exposure window.
Patch Information
Fixed releases are published by the LemonLDAP::NG project: Release 2.16.9, Release 2.21.5, and Release 2.23.3. The fix corrects the getApacheSession() invocation so the state session is stored under an isolated kind and cannot be replayed as an SSO session cookie.
Workarounds
- Replace default => accept virtual host rules with rules that require $authenticationLevel above a minimum threshold or a non-empty $uid.
- Temporarily disable the GitHub and LinkedIn authentication backends in the LemonLDAP::NG manager if an immediate upgrade is not feasible.
- Front the portal with a web application firewall rule that rejects portal session cookies whose value matches a recently issued state parameter.
# Example: harden virtual host access rules in lemonldap-ng.ini / Manager
# Replace permissive default with an authentication-level requirement
accessRule: $authenticationLevel >= 2 and $uid ne ''
default: deny
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

