GitHub Security Advisory: GHSA-h5j9-cvrw-v5qh
Package: github.com/knadh/listmonk (GO)
Severity: HIGH (CVSS 7.1)
CWE: CWE-613: Insufficient Session Expiration
Vulnerable versions: >= 1.1.1-0[PII_REDACTED]0858-319053dd7a90, < 1.1.1-0[PII_REDACTED]3754-1b5e8d38c778
Patched in: 1.1.1-0[PII_REDACTED]3754-1b5e8d38c778

Summary: listmonk's active sessions remain valid after password reset and password change

Details:
### Summary
A session management vulnerability allows previously issued authenticated sessions to remain valid after sensitive account security changes, specifically password reset and password change. As a result, an attacker who has already obtained a valid session cookie can retain access to the account even after the victim changes or resets their password.

This weakens account recovery and session security guarantees. I reproduced the issue on listmonk v6.0.0.

### Details
The application updates account credentials successfully, but existing active sessions are not revoked afterward.

This behavior was confirmed in two flows:

1. **Password reset flow**
   - A user resets their password through the forgot/reset flow.
   - The old password becomes invalid.
   - The new password works.
   - However, a session cookie issued **before** the reset remains valid and continues to authenticate successfully.

2. **Authenticated password change flow**
   - The same user logs in from two separate sessions.
   - Using session A, the password is changed through the authenticated profile endpoint.
   - The old password becomes invalid.
   - The new password works.
   - However, session B, issued before the password change, remains valid and continues to authenticate successfully.

From the source review, the reset flow consumes the reset token, updates the password, and creates a fresh session, but there does not appear to be any revocation of older sessions. The same applies to the profile password change flow.

Relevant code areas observed during review:
- `cmd/auth.go` — forgot/reset flow
- `cmd/users.go` — authenticated profile update flow
- `internal/core/users.go` — password update path

Additionally:
- It was verified that reset links are single-use.
- It was verified that password reset on a TOTP-enabled account still enforces TOTP on fresh login.
- However, already-issued sessions still remain valid after reset.

### PoC
#### Case 1: Password reset does not revoke existing session

1. Create or use a normal user account.
2. Log in as that user and save the authenticated session cookie.
3. Trigger forgot-password for the account.
4. Use the emailed reset link and set a new password.
5. Verify:
   - the old password no longer works
   - the new password works
6. Replay the **old pre-reset session cookie** against an authenticated endpoint such as `/api/profile`.

Example validation request:
```http
GET /api/profile HTTP/1.1
Host: 127.0.0.1:9000
Cookie: session=<old_pre_reset_session>
```

Observed result:

Server returns `HTTP/1.1 200 OK`
Response contains the authenticated user profile

#### Case 2: Password change does not revoke other active sessions

1. Log in twice as the same user and save two authenticated session cookies:
   - session A
   - session B

2. Using session A, change the password through the authenticated profile update endpoint.

3. Verify:
   - the old password no longer works
   - the new password works

4. Replay session B