CVE-2026-54739 Overview
Lemmy is a federated link aggregator and forum platform for the fediverse. CVE-2026-54739 is a user enumeration vulnerability [CWE-204] in the login endpoint located at crates/api/api/src/local_user/login.rs. The endpoint returns distinguishable responses depending on whether the submitted username_or_email value maps to an existing account. Unknown accounts trigger an HTTP 404 NotFound response, while existing accounts with an incorrect password return HTTP 400 with LemmyErrorType::IncorrectLogin. An unauthenticated attacker can use this discrepancy to confirm registered usernames or email addresses. The confirmed identifiers can then feed targeted credential stuffing, password spraying, or social engineering campaigns. The issue is fixed in Lemmy 0.19.19 and 1.0.0-beta.1.
Critical Impact
Unauthenticated attackers can enumerate valid usernames and email addresses on any Lemmy instance prior to the fixed versions, enabling targeted follow-on attacks.
Affected Products
- Lemmy versions prior to 0.19.19
- Lemmy 1.0.0 pre-release versions prior to 1.0.0-beta.1
- Any federated Lemmy instance exposing the login API
Discovery Timeline
- 2026-08-19 - CVE-2026-54739 published to NVD
- 2026-08-19 - Last updated in NVD database
Technical Details for CVE-2026-54739
Vulnerability Analysis
The vulnerability resides in the login handler in crates/api/api/src/local_user/login.rs. The handler calls LocalUserView::find_by_email_or_name to resolve the submitted identifier. When the identifier does not match any account, the function propagates a NotFound error, which the API surfaces as HTTP 404. When the identifier matches an existing account but the password is incorrect, the handler proceeds through the bcrypt verification path and returns HTTP 400 with LemmyErrorType::IncorrectLogin.
This observable divergence exposes account existence over an unauthenticated network path. Attackers can script large-scale enumeration against username lists or breach corpora and confirm which identifiers exist on a target instance. In addition to the status-code discrepancy, the two code paths take measurably different amounts of time because only the existing-account path performs a bcrypt hash verification. This produces a timing side channel even if the HTTP status codes were normalized.
Root Cause
The root cause is inconsistent error handling in the authentication flow. The lookup and password verification stages return distinct error types that map to distinct HTTP responses. There is no constant-time or constant-response wrapper around the identifier resolution step, which violates the principle that authentication failures should be indistinguishable regardless of which factor failed.
Attack Vector
The attack is remote, unauthenticated, and requires no user interaction. An attacker sends POST requests to the login endpoint with candidate usernames or emails and observes the response. The following patch excerpts from the official fix illustrate both the vulnerable pattern and the constant-time correction.
// Fix applied in Lemmy 1.0.0-beta.1 (commit 4d235a1b)
api::{Login, LoginResponse},
};
use lemmy_utils::error::{LemmyErrorType, LemmyResult};
use tokio::task::spawn_blocking;
pub async fn login(
Json(data): Json<Login>,
req: HttpRequest,
context: Data<LemmyContext>,
) -> LemmyResult<Json<LoginResponse>> {
let site_view = SiteView::read_local(&mut context.pool()).await?;
let password = data.password.clone();
// Fetch that username / email
let username_or_email = data.username_or_email.clone();
let local_user_view =
match LocalUserView::find_by_email_or_name(&mut context.pool(), &username_or_email).await {
Ok(o) => o,
Err(e) => {
spawn_blocking(move || {
// Dummy bcrypt verify for constant timing
let _ = verify(
&data.password,
"$2b$12$dt1Xr.ZGO8W1YtWoJRtpauM1.bkBt2C1Tck3XgZTSoBQRdGuYCTTy",
);
})
.await?;
return Err(e);
}
Source: Lemmy commit 4d235a1b
The 0.19.x backport applies an equivalent dummy bcrypt verification on the not-found path to equalize timing behavior. Source: Lemmy commit 59e968a5.
Detection Methods for CVE-2026-54739
Indicators of Compromise
- High-volume POST requests to /api/v3/user/login or /api/v4/user/login from a single source or distributed set of sources
- Sequential submissions with rotating username_or_email values and static or empty passwords
- Elevated ratio of HTTP 404 responses from the login endpoint indicating scans for valid accounts
- Requests originating from known credential-stuffing infrastructure or anonymizing proxies
Detection Strategies
- Alert when the login endpoint returns more than a threshold of HTTP 404 responses per source IP within a short window
- Correlate login attempts to identify enumeration patterns spanning multiple identifiers with a constant password value
- Baseline normal login failure rates per instance and alert on statistical deviations
Monitoring Recommendations
- Ingest reverse-proxy and Lemmy application logs into a centralized analytics platform for query and correlation
- Track the ratio of HTTP 404 to HTTP 400 responses on the login route as an enumeration indicator
- Monitor source IP diversity per unique username submitted to distinguish enumeration from credential stuffing
How to Mitigate CVE-2026-54739
Immediate Actions Required
- Upgrade Lemmy instances to version 0.19.19 for the 0.19.x branch or 1.0.0-beta.1 for the 1.0.x branch
- Review reverse-proxy logs for prior enumeration activity and identify accounts that may have been exposed
- Notify users of any enumerated accounts and encourage strong, unique passwords and two-factor authentication where supported
Patch Information
The fix is available in Lemmy 0.19.19 and Lemmy 1.0.0-beta.1. The patch is tracked in GitHub Pull Request #6531 and GitHub Pull Request #6535. Full advisory details are available in GHSA-xgg7-8hvq-8m65 and the Lemmy 0.19.19 release announcement.
Workarounds
- Apply strict rate limiting on the login endpoint at the reverse proxy or WAF layer to slow enumeration attempts
- Deploy WAF rules that normalize response codes for authentication failures on the /user/login route
- Restrict administrative or high-value accounts to identifiers not derivable from public profiles
# Example nginx rate limit for the login endpoint
limit_req_zone $binary_remote_addr zone=lemmy_login:10m rate=5r/m;
server {
location ~ ^/api/v[34]/user/login$ {
limit_req zone=lemmy_login burst=5 nodelay;
proxy_pass http://lemmy_backend;
}
}
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

