Apr 2, 2026·7 min read·31 visits
Listmonk prior to version 6.1.0 does not invalidate active session tokens upon password changes or resets. Attackers with stolen session cookies can maintain persistent authenticated access despite victim credential rotation.
Listmonk versions 4.1.0 through 6.0.x contain an Insufficient Session Expiration vulnerability (CWE-613) within the application's authentication lifecycle handlers. The software fails to revoke existing authenticated sessions when a user undergoes a password reset or performs an intentional password change. This oversight enables an attacker who has acquired a valid session cookie to maintain unauthorized, persistent access to the compromised account, successfully bypassing the primary defense mechanism of credential rotation.
Listmonk is an open-source, self-hosted newsletter and mailing list manager written in Go and backed by a PostgreSQL database. The software relies on server-side session management to handle administrator and user authentication. Sessions are generated upon successful login, stored persistently in the database, and tracked via an HTTP cookie delivered to the client.
CVE-2026-34828 identifies a structural flaw in how listmonk manages the lifecycle of these sessions during critical security events. Specifically, the application exhibits an Insufficient Session Expiration vulnerability (CWE-613). When an account password is changed or reset, the application updates the authentication credentials but fails to terminate preexisting sessions associated with that user.
This architecture fundamentally decouples the session state from the credential state. Consequently, the primary remediation strategy for suspected account compromise—rotating the account password—fails to neutralize the threat. An attacker who has previously compromised an active session token retains access until the original token reaches its natural Time-To-Live (TTL) expiration.
The attack surface requires the threat actor to have preemptively obtained a valid session cookie. This is typically achieved through secondary attack vectors, such as Cross-Site Scripting (XSS), physical access to an unlocked terminal, endpoint malware, or network traffic interception on insecure connections.
The root cause of CVE-2026-34828 resides in the application's user profile update and password reset routines. The application tracks user sessions via a dedicated sessions table in the PostgreSQL database. The authentication middleware validates incoming requests by extracting the session ID from the cookie, verifying its cryptographic signature, checking its TTL, and confirming its presence in the database.
During a password reset flow, orchestrated by the doResetPassword handler in cmd/auth.go, the application successfully receives the valid reset token and processes the new password. The backend then issues a SQL UPDATE statement targeting the users table, overwriting the existing password_hash with the newly generated bcrypt hash.
However, this routine lacks a corresponding cleanup operation against the sessions table. The internal/core/users.go library, which abstracts the database interactions, did not implement any logic to invalidate or purge session records tied to the affected user ID.
Because the session validation middleware strictly evaluates the token's validity against the sessions table without cross-referencing a password version identifier or checking a last_password_change timestamp, the preexisting session tokens remain entirely valid. The application logic assumes session validity based solely on the token's existence, ignoring state changes in the underlying credential store.
The vulnerability was resolved in commit db82035d619348949512dafdaf60c86037cafc9e. The fix introduces a unified mechanism to purge active sessions from the database when credential-altering events occur. The core addition is a new parameterized SQL query in queries/users.sql.
-- Pre-patch: No session deletion query existed for user updates.
-- Post-patch: Added to queries/users.sql
-- name: delete-user-sessions
DELETE FROM sessions WHERE data->>'user_id' = $1 AND ($2 = '' OR id != $2);This query targets the JSONB data column in the sessions table to match the specific user ID. It conditionally spares the currently active session if an ID is provided in parameter $2, preventing the user initiating the password change from being unexpectedly logged out of their current device.
The Go backend was updated to utilize this query. In cmd/users.go, the handler responsible for processing user profile updates was modified to invoke the new DeleteUserSessions wrapper function.
// Modified cmd/users.go - UpdateUserProfile handler
func (a *App) UpdateUserProfile(c echo.Context) error {
// ... (input validation and user update logic)
// Post-patch addition: Revoke all other sessions upon password change
if req.Password != "" {
currentSession := auth.GetSessionID(c)
if err := a.core.DeleteUserSessions(user.ID, currentSession); err != nil {
a.log.Errorf("failed to clear sessions: %v", err)
}
}
return c.JSON(http.StatusOK, true)
}A similar implementation was added to cmd/auth.go for the unauthenticated password reset flow, where parameter $2 is explicitly left empty ("") to indiscriminately terminate all sessions for that user ID.
Exploitation of CVE-2026-34828 requires an attacker to possess a stolen session cookie. The exploit lifecycle begins when the threat actor compromises the victim's session, typically through client-side vulnerabilities, local machine access, or session hijacking techniques.
Once the victim detects suspicious activity, the standard incident response protocol dictates changing the account password. The victim authenticates to listmonk and navigates to the Profile settings to execute a password change, or utilizes the "Forgot Password" feature to reset the credentials via email.
> [!NOTE] > The vulnerability execution occurs precisely when the server processes the password change. The application commits the new password hash to the database but leaves the attacker's active session undisturbed in the session store.
The attacker continues to interface with the listmonk API by injecting the originally stolen session cookie into subsequent HTTP requests. The server processes the session identifier, finds a matching and unexpired record in the database, and authorizes the transaction.
GET /api/profile HTTP/1.1
Host: listmonk.example.local
Cookie: session=a8b3c9d2...
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": 1,
"username": "admin",
"role": "super-admin"
}The persistence is maintained until the stolen session reaches its absolute expiration time, granting the attacker uninterrupted administrative or user-level access to the mailing list infrastructure.
The exploitation of this vulnerability results in persistent, unauthorized access to the listmonk instance. The severity is highly dependent on the privileges associated with the compromised session. If the session belongs to a super-admin, the threat actor retains complete control over the application, including the ability to exfiltrate subscriber databases, modify mailing lists, alter application configurations, and distribute malicious campaigns.
The CVSS v3.1 vector evaluates to 7.1 (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:N). The network attack vector (AV:N) and low attack complexity (AC:L) reflect the ease of replaying a valid cookie over the network. The privileges required (PR:L) denote that the attacker acts within the context of the compromised user account. Confidentiality impact (C:H) is high due to the exposure of personal subscriber data.
This vulnerability fundamentally degrades the integrity of the application's incident response mechanisms. System administrators and users operating under the assumption that a password reset secures a compromised account remain unknowingly exposed to continuous exploitation.
The definitive remediation for CVE-2026-34828 is upgrading the listmonk application to version 6.1.0 or later. This release incorporates the DeleteUserSessions logic, ensuring that session lifecycles are correctly tied to credential validity.
For environments where immediate patching is administratively or technically unfeasible, a manual mitigation strategy must be employed. Administrators can enforce a global session invalidation by directly interacting with the PostgreSQL database. Executing DELETE FROM sessions; will immediately terminate all active sessions, forcing all users to re-authenticate using their current credentials.
To detect potential historical exploitation, security engineers should audit the application logs and database records. Evidence of exploitation may present as multiple distinct IP addresses utilizing the same user ID within the sessions table immediately following a password reset event recorded in the system audit logs.
Network defenders can additionally implement Web Application Firewall (WAF) rules designed to monitor for session anomalies. Detecting a single session cookie generating requests from geographically disparate locations within an impossibly short timeframe (impossible travel) serves as a robust indicator of session theft and concurrent usage.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
listmonk knadh | >= 4.1.0, < 6.1.0 | 6.1.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-613 |
| Attack Vector | Network |
| CVSS Score | 7.1 (High) |
| Exploit Status | Proof of Concept (PoC) available |
| KEV Status | Not Listed |
| Impact | Persistent Unauthorized Access |
The system does not adequately terminate a user session upon critical account lifecycle events, allowing an attacker to maintain persistent unauthorized access.
CVE-2026-48596 is an Improper Neutralization of CRLF Sequences in HTTP Headers (HTTP Request/Response Splitting, CWE-113) in the Elixir Tesla HTTP client. The flaw resides in how multipart content-type parameters are joined and serialized, enabling attackers to inject arbitrary headers or split HTTP requests when applications pass untrusted inputs to the parameters of multipart uploads.
An improper handling of highly compressed data (decompression bomb) vulnerability exists in the Elixir Tesla HTTP client when utilizing response decompression middlewares. By serving highly compressed responses or stacked content-encoding headers, a malicious server can cause arbitrary heap exhaustion, leading to a denial of service (DoS) crash in the BEAM virtual machine.
A high-severity security vulnerability in Elixir's Tesla HTTP client library (CVE-2026-48595) allows unauthenticated remote attackers to harvest sensitive credentials, including Authorization headers and cookies. The flaw resides in the 'Tesla.Middleware.FollowRedirects' component, which performs case-sensitive lookups when stripping credentials during cross-origin redirects. Because HTTP headers are case-insensitive by RFC specifications, standard canonical casing (e.g., 'Authorization') bypasses the lowercase-only blocklist, leaking tokens to untrusted external redirect destinations.
CVE-2026-48597 is a high-severity Denial of Service (DoS) vulnerability in the Elixir HTTP client library Tesla (specifically involving the Mint adapter) that allows an unauthenticated remote attacker to cause an unrecoverable crash of the Erlang Virtual Machine (BEAM). The flaw arises from the dynamic conversion of untrusted URL schemes into Erlang atoms without validation, leading to global atom table exhaustion.
An Improper Encoding or Escaping of Output vulnerability (CWE-116) in elixir-tesla allowed unauthenticated remote code execution or request smuggling via unescaped Content-Disposition parameters in multipart form-data requests.
CVE-2026-49851 is a high-severity algorithmic complexity vulnerability in the Mistune Markdown parser. Under specific conditions involving dense, unmatched nesting of opening square brackets, the parser fallback loops degrade from linear execution time to a worst-case quadratic complexity. This allows unauthenticated remote attackers to trigger complete CPU exhaustion and subsequent Denial of Service with a highly compact payload.