CVE-2026-33877 Overview
ApostropheCMS, an open-source Node.js content management system, contains a timing side-channel vulnerability in the password reset endpoint (/api/v1/@apostrophecms/login/reset-request) that allows unauthenticated attackers to enumerate valid usernames and email addresses. The vulnerability exists in versions 4.28.0 and prior, where measurable response time differences can be exploited to distinguish between valid and invalid user accounts.
Critical Impact
This timing side-channel vulnerability enables automated enumeration of valid user accounts, which can be leveraged for credential stuffing attacks or targeted phishing campaigns against ApostropheCMS installations with password reset functionality enabled.
Affected Products
- ApostropheCMS versions 4.28.0 and prior
- Only instances with passwordReset option explicitly enabled (defaults to false)
- Node.js deployments running vulnerable ApostropheCMS versions
Discovery Timeline
- 2026-04-15 - CVE CVE-2026-33877 published to NVD
- 2026-04-15 - Last updated in NVD database
Technical Details for CVE-2026-33877
Vulnerability Analysis
This vulnerability represents a classic timing side-channel attack (CWE-208) in the password reset flow. The core issue lies in the asymmetric timing behavior of the resetRequest handler. When a user is not found in the database, the handler returns after a fixed 2-second artificial delay. However, when a valid user is found, the system performs additional operations—including a MongoDB update and SMTP email transmission—without equivalent delay normalization, resulting in measurably different response times.
The endpoint accepts both username and email parameters via an $or MongoDB query, expanding the attack surface. Additionally, the existing checkLoginAttempts throttling mechanism only applies to the login flow, leaving the password reset endpoint without rate limiting protection.
Root Cause
The root cause is the inconsistent application of timing delays in the password reset flow. The original implementation introduced a fixed delay for error cases but failed to normalize response times when valid users are found and email operations are performed. This creates an observable timing oracle that leaks information about account validity.
Attack Vector
An unauthenticated attacker with network access can exploit this vulnerability by sending multiple password reset requests with different email addresses or usernames and measuring the response times. Valid accounts will exhibit different response timing patterns compared to invalid accounts. The lack of rate limiting on this endpoint enables automated high-volume enumeration attacks.
},
...self.isPasswordResetEnabled() && {
async resetRequest(req) {
- const wait = (t = 2000) => Promise.delay(t);
+ const MIN_RESPONSE_TIME = 2000;
+ const startTime = Date.now();
const site = (req.headers.host || '').replace(/:\d+$/, '');
const email = self.apos.launder.string(req.body.email);
if (!email.length) {
throw self.apos.error('invalid', req.t('apostrophe:loginResetEmailRequired'));
}
let user;
- // error not reported to browser for security reasons
try {
user = await self.getPasswordResetUser(req.body.email);
} catch (e) {
self.apos.util.error(e);
}
if (!user) {
- await wait();
self.apos.util.error(
`Reset password request error - the user ${email} doesn\`t exist.`
);
- return;
- }
- if (!user.email) {
- await wait();
+ } else if (!user.email) {
self.apos.util.error(
`Reset password request error - the user ${user.username} doesn\`t have an email.`
Source: GitHub Commit Update
Detection Methods for CVE-2026-33877
Indicators of Compromise
- High volume of requests to /api/v1/@apostrophecms/login/reset-request endpoint from single IP addresses or IP ranges
- Sequential or pattern-based email/username attempts in password reset requests
- Unusual response time analysis patterns in web server logs indicating timing measurement activity
- Burst traffic to password reset endpoints outside normal user behavior patterns
Detection Strategies
- Implement web application firewall (WAF) rules to detect and alert on high-frequency password reset requests
- Monitor for statistical anomalies in request rates to the password reset endpoint
- Deploy log analysis to identify sequential enumeration patterns (alphabetical, dictionary-based, or leaked credential lists)
- Enable application-level logging to track password reset request failures and success patterns
Monitoring Recommendations
- Set up alerting thresholds for password reset request volumes exceeding baseline patterns
- Correlate password reset enumeration attempts with subsequent authentication failures or successful logins
- Monitor for requests from known malicious IP addresses or Tor exit nodes targeting the password reset endpoint
- Track response time distributions for the password reset endpoint to detect ongoing exploitation attempts
How to Mitigate CVE-2026-33877
Immediate Actions Required
- Upgrade ApostropheCMS to version 4.29.0 or later, which contains the security fix
- If upgrade is not immediately possible, consider temporarily disabling the passwordReset option if not critical to operations
- Implement rate limiting at the reverse proxy or WAF level for the /api/v1/@apostrophecms/login/reset-request endpoint
- Review logs for signs of prior exploitation or enumeration attempts
Patch Information
The vulnerability has been fixed in ApostropheCMS version 4.29.0. The fix normalizes response times by tracking elapsed time and ensuring all responses take a minimum consistent duration, eliminating the timing oracle. The patch can be reviewed in the GitHub commit. Additional details are available in the GitHub Security Advisory GHSA-mj7r-x3h3-7rmr.
Workarounds
- Disable the passwordReset option in ApostropheCMS configuration if the feature is not required
- Implement network-level rate limiting on the password reset endpoint using reverse proxy or WAF
- Add CAPTCHA or proof-of-work challenges to the password reset flow to slow automated enumeration
- Deploy IP-based throttling rules to limit requests per IP address to the affected endpoint
# Example nginx rate limiting configuration for password reset endpoint
limit_req_zone $binary_remote_addr zone=reset_limit:10m rate=5r/m;
location /api/v1/@apostrophecms/login/reset-request {
limit_req zone=reset_limit burst=2 nodelay;
limit_req_status 429;
proxy_pass http://apostrophe_backend;
}
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.


