Mar 1, 2026·6 min read·2 visits
Authenticated low-privilege users can access the email addresses of all system users via the Control Panel API, bypassing the 'view users' permission. Additionally, insufficent sandboxing in the Antlers template engine could allow access to sensitive configuration variables.
A missing authorization vulnerability (CWE-862) in Statamic CMS allows authenticated users with Control Panel access to retrieve sensitive information, including email addresses of all users and potentially system configuration secrets. The flaw exists in the user selection fieldtype endpoint and the Antlers templating engine, which failed to adequately sandbox execution or filter data based on permissions.
Statamic CMS, a flat-file content management system built on Laravel, utilizes a dynamic Control Panel (CP) for content editing. A vulnerability was identified in the mechanism used to populate the 'User' fieldtype within the CP. This component is responsible for allowing content editors to associate specific system users with content entries, such as assigning an author to a blog post.
The specific flaw lies in the API endpoint serving data to this fieldtype. When the frontend interface requests a list of users to populate the selection dropdown, the backend responds with a serialized JSON representation of user objects. Crucially, this endpoint failed to verify whether the requesting user held the specific 'view users' permission before including sensitive attributes—most notably email addresses—in the response payload.
While the primary vector concerns the unauthorized retrieval of user emails, a secondary and related vector was discovered in the Antlers templating engine. This engine, used for rendering content, allowed for method invocation on user objects and access to the global application configuration. This could theoretically allow an attacker to inject Antlers syntax into a field that is subsequently rendered, leaking environment variables or executing unauthorized object methods.
The root cause of this vulnerability is Missing Authorization (CWE-862) within the data serialization layer of the Control Panel API. In Laravel-based applications, API responses are often generated by serializing Eloquent models or Resource classes. In this instance, the controller responsible for the User fieldtype data (/cp/fields/users/data) returned a collection of user objects.
The system relied on the frontend UI to hide elements the user wasn't supposed to see, rather than filtering the data at the source. The backend logic did not implement a gate check (e.g., $user->can('view users')) prior to serializing the user data. Consequently, even if a user role was restricted from managing users in the UI, the underlying API call would still return the full dataset, including private fields.
Regarding the Antlers template vector, the issue stemmed from an overly permissive evaluation context. The template engine allowed access to the full config()->all() array. This implies that any configuration value loaded into memory—including database credentials, API keys, and application secrets stored in .env—was accessible via template tags (e.g., {{ config:app:key }}). The lack of a strict whitelist or a 'sandbox' mode for untrusted user input allowed this data traversal.
The remediation involved hardening both the User Resource serialization and the Antlers engine. Below is a reconstruction of the critical changes based on the patch methodology.
1. User Resource Redaction
The primary fix modifies the resource class to explicitly check permissions before returning the email attribute. Previously, the toArray or equivalent method likely dumped all model attributes.
// VULNERABLE CODE (Conceptual)
public function toAugmentedArray()
{
return [
'id' => $this->id(),
'name' => $this->name(),
'email' => $this->email(), // Always returned
// ... other attributes
];
}
// PATCHED CODE (Conceptual)
public function toAugmentedArray()
{
$data = [
'id' => $this->id(),
'name' => $this->name(),
];
// Explicit authorization check
if (User::current()->can('view users')) {
$data['email'] = $this->email();
}
return $data;
}2. Antlers Configuration Whitelisting
To address the configuration leak, Statamic replaced the full config exposure with a strict allowlist. This prevents attackers from accessing arbitrary keys like database.connections or app.key.
// VULNERABLE: Statamic\View\Cascade.php
public function config()
{
// Returns the entire configuration tree
return config()->all();
}
// PATCHED: Statamic\View\Cascade.php
public function config()
{
// Only expose safe, whitelisted keys
return array_intersect_key(
config()->all(),
array_flip(config('statamic.system.view_config_allowlist', []))
);
}Additionally, a global state flag isEvaluatingUserData was introduced. When parsing user-provided content (like a bio or title), this flag is set to true, causing the engine to block method calls on objects, effectively neutralizing the remote code execution potential of the template injection.
Exploitation of the Information Disclosure vulnerability requires authenticated access to the Statamic Control Panel. The privilege level can be minimal (e.g., a restricted 'Author' or 'Editor' role). The attack does not require specialized tooling; a standard web browser suffices.
Step 1: Session Establishment The attacker logs into the Statamic Control Panel using valid credentials.
Step 2: Endpoint Discovery The attacker navigates to any collection entry or blueprint configuration that utilizes the 'User' fieldtype. Using the browser's Developer Tools (Network tab), the attacker observes the XHR requests generated when the page loads or when interacting with the user selection dropdown.
Step 3: Data Exfiltration
The attacker identifies a request to /cp/fields/users/data (or similar). Inspecting the JSON response reveals an array of user objects. Even if the current user lacks the view users permission, the JSON payload contains the email field for every user in the system, including Administrators.
Step 4: Antlers Injection (Secondary)
If the attacker has permission to edit content that is rendered via Antlers (e.g., a previewable field), they may attempt to inject syntax such as {{ config:app:debug }}. In unpatched versions, this would render the debug status. More critically, prior to the whitelist implementation, {{ config:database:connections:mysql:password }} could theoretically leak database credentials if the view context was not properly sanitized.
The primary impact of this vulnerability is the loss of confidentiality regarding user data. By harvesting email addresses, an attacker can facilitate targeted phishing campaigns against high-value targets (e.g., administrators) or conduct credential stuffing attacks if the organization lacks Single Sign-On (SSO) or Multi-Factor Authentication (MFA).
The secondary impact regarding Antlers template injection is more severe but conditional. If an attacker can successfully coerce the engine to dump configuration data, the compromise escalates from Information Disclosure to a potential full system compromise. Leaking APP_KEY allows for session forgery, while leaking database credentials or AWS keys allows for lateral movement and data theft.
CVSS v3.1 Analysis:
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:NCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
Statamic CMS Statamic | < 5.73.11 | 5.73.11 |
Statamic CMS Statamic | >= 6.0.0 < 6.4.0 | 6.4.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-862 |
| Vulnerability Type | Missing Authorization |
| CVSS Score | 6.5 (Medium) |
| Attack Vector | Network (Authenticated) |
| Impact | Information Disclosure |
| EPSS Score | 0.00027 (~7%) |