Mar 4, 2026·4 min read·3 visits
Unauthenticated attackers can trigger activation emails for arbitrary user IDs in Craft CMS versions prior to 5.9.0-beta.2 and 4.17.0-beta.2. This exposes user enumeration vectors and potential spam risks.
A security vulnerability in Craft CMS allows unauthenticated remote attackers to trigger activation emails for pending user accounts. This flaw stems from an improper access control configuration in the `UsersController`, permitting anonymous access to the `actionSendActivationEmail` endpoint. Exploitation facilitates user enumeration and potential phishing campaigns by allowing attackers to verify the existence of user IDs and spam registered email addresses.
Craft CMS contains an improper access control vulnerability within its user management module. The affected component, UsersController, handles administrative actions related to user accounts, including the dispatch of activation emails for pending registrations. In affected versions, the specific action responsible for this task (actionSendActivationEmail) is inadvertently exposed to unauthenticated users via the public web interface.
By sending a crafted HTTP request to the application, a remote attacker can force the system to generate and send an activation email to the email address associated with a specific user ID. This occurs without requiring administrative privileges or a valid session. While the attacker cannot directly intercept the email or modify its destination, this behavior leaks information about the existence of user accounts and abuses the server's trust relationship with its email provider.
The vulnerability is classified as an Authorization Bypass Through User-Controlled Key (CWE-639). The root cause lies in the configuration of the allowAnonymousConfig property within src/controllers/UsersController.php. Craft CMS uses this property to explicitly whitelist actions that should be accessible without a session, such as login or password reset requests.
Prior to the patch, the send-activation-email action was included in this whitelist. Consequently, the application's request handling pipeline skipped standard authentication and authorization checks for this specific route. The controller method actionSendActivationEmail accepted a userId parameter from the POST body and immediately proceeded to process the activation logic, assuming the caller was authorized simply because the route was publicly exposed.
The vulnerability is evident in the comparison between the vulnerable controller configuration and the patched version. In the vulnerable code, the allowAnonymousConfig array acts as an explicit bypass for authentication filters.
Vulnerable Code (src/controllers/UsersController.php):
public $allowAnonymousConfig = [
// ... other actions ...
// CRITICAL: Explicitly allowing anonymous access
'send-activation-email' => self::ALLOW_ANONYMOUS_LIVE | self::ALLOW_ANONYMOUS_OFFLINE,
];
public function actionSendActivationEmail(): ?Response
{
// Only checks for POST method, no permission checks
$this->requirePostRequest();
$userId = $this->request->getRequiredBodyParam('userId');
// ... triggers email sending logic ...
}Patched Code:
The fix involves removing the action from the anonymous whitelist and implementing strict access controls. The developer introduced a userActionChecks method that enforces administrative privileges.
// Action removed from $allowAnonymousConfig
public function actionSendActivationEmail(): ?Response
{
// NEW: Enforce strict checks before processing
$this->userActionChecks();
$userId = $this->request->getRequiredBodyParam('userId');
// ...
}
private function userActionChecks(): void
{
// 1. Require Pro edition
Craft::$app->requireEdition(Craft::Pro);
// 2. Require POST method
$this->requirePostRequest();
// 3. Require request to originate from Control Panel
$this->requireCpRequest();
// 4. Require specific administrative permission
$this->requirePermission('editUsers');
}Exploitation requires no authentication. An attacker sends a POST request to the action URL, typically /index.php with a query parameter routing to the controller action (e.g., ?p=admin/actions/users/send-activation-email or just actions/users/send-activation-email), or via the friendly URL if configured.
Attack Steps:
POST request containing a userId parameter. The ID is typically an integer.userId values (e.g., 1, 2, 3...).
The primary impact of CVE-2026-29069 is Information Disclosure (User Enumeration) and abuse of functionality. While the CVSS v4.0 score is Medium (6.9), the implications for enterprise environments are significant.
Consequences:
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
Craft CMS Pixel & Tonic | >= 5.0.0-RC1, < 5.9.0-beta.2 | 5.9.0-beta.2 |
Craft CMS Pixel & Tonic | >= 4.0.0-RC1, < 4.17.0-beta.2 | 4.17.0-beta.2 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-639 |
| CVSS v4.0 | 6.9 (Medium) |
| Attack Vector | Network |
| Attack Complexity | Low |
| Privileges Required | None |
| Exploit Status | None / No Known Exploit |
Authorization Bypass Through User-Controlled Key