Feb 12, 2026·6 min read·4 visits
Authenticated users with basic Control Panel access can view restricted assets (PDFs, SVGs, Thumbnails) by bypassing permission checks on specific controller routes. Patch involves adding missing authorization gates.
A granular access control failure in Statamic CMS allows authenticated Control Panel users to bypass container-specific permissions. By directly accessing asset controllers for PDFs, SVGs, and thumbnails, low-privilege users can view and download files from restricted containers (like 'Private' or 'HR') that they are explicitly denied access to in the UI.
Statamic is the darling of the flat-file CMS world. It relies heavily on Laravel, which usually implies a robust security architecture. Most organizations set up their Control Panel (CP) like a fortress: you need a login, you need a role, and you need specific permissions to touch the sensitive stuff. You might have a 'Marketing' role that can edit the blog, and an 'HR' role that handles employee contracts.
The assumption is simple: if the Marketing intern tries to open the 'Executive Bonuses' folder, the system should slap their hand away. And if they use the UI, it does. The folder doesn't even show up in the sidebar. Out of sight, out of mind, right?
Wrong. CVE-2026-25633 is a classic case of "Security by UI Obscurity." While the frontend politely hides the links to sensitive assets, the backend controllers responsible for rendering previews (PDFs, SVGs, thumbnails) were completely agnostic to your permissions. They didn't care who you were, as long as you had a badge to get into the building. It’s like guarding the front door of a bank but leaving the vault wide open for anyone who just walks past the teller.
The root cause here is a failure to apply granular Authorization (AuthZ) at the controller level. In Laravel applications, you typically have middleware that acts as a broad filter. Statamic uses cp.access to ensure that the user is logged in and allowed to access the Control Panel. This is the first line of defense.
However, once inside, specific actions require specific checks. If you want to view a file in the private container, the code should check $user->can('view', $asset). In the affected versions of Statamic, several controllers—specifically PdfController, SvgController, and ThumbnailController—skipped this step entirely.
These controllers take a Base64-encoded ID, decode it to find the file path on the disk, and stream the content back to the browser. They assumed that if you knew the ID, you probably had the right to see it. This implies a trust model where knowledge of an identifier equals authorization to access the resource, which is a dangerous fallacy when those identifiers are predictable.
Let's look at the smoking gun in Statamic\Http\Controllers\CP\Assets\PdfController. The vulnerable code simply took the asset ID and served it up. It relied entirely on the surrounding middleware for protection, which was insufficient for granular control.
Vulnerable Code (Simplified):
public function show($encoded_id)
{
$asset = Asset::find(base64_decode($encoded_id));
if (! $asset) {
abort(404);
}
// Look ma, no hands! (No authorization check)
return $asset->download();
}The Fix (Commit 5a6f472):
The fix is elegantly simple but highlights exactly what was missing. The developers added a standard Laravel authorization gate using $this->authorize(). This forces the application to run the specific policy associated with viewing that asset.
public function show($encoded_id)
{
$asset = Asset::find(base64_decode($encoded_id));
if (! $asset) {
abort(404);
}
// The Guard Dog is now awake
$this->authorize('view', $asset);
return $asset->download();
}This same pattern was applied across the SvgController and ThumbnailController. If the user's role does not explicitly grant permission to the container holding the asset, the application now throws a 403 Forbidden.
To exploit this, an attacker needs two things: a valid low-privilege account with CP access, and the ability to guess asset IDs. In Statamic, asset IDs are constructed using the format container_handle::path/to/file.ext.
Let's assume there is a restricted container named financials containing a file q1_report.pdf. The ID is financials::q1_report.pdf. An attacker simply needs to Base64 encode this string to generate the payload.
Attack Chain:
private or docs. They guess a filename, perhaps standardizing on dates or common terms.private::hr/layoff_list.pdfcHJpdmF0ZTo6aHIvbGF5b2ZmX2xpc3QucGRmhttps://target.com/cp/pdfs/cHJpdmF0ZTo6aHIvbGF5b2ZmX2xpc3QucGRm.Because the PdfController didn't check if the user had access to the private container, the browser renders the PDF immediately. This works for SVGs and generic thumbnails as well, allowing an attacker to map out the file structure of restricted directories visually.
While this vulnerability scores a relatively modest 4.3 on the CVSS scale, the real-world impact depends entirely on what you are hiding. For a blog, this is a nothing-burger. For a corporate intranet or a client portal, it's a disaster.
This is a pure Confidentiality breach. It allows lateral movement of data access within the application. A user trusted to edit the "Lunch Menu" should not be able to read the "Merger Acquisition Strategy".
Furthermore, because this affects endpoints often used for automated preview generation, an attacker could potentially script an enumeration attack, iterating through likely filenames and checking for 200 OK responses vs 404s, effectively scraping the entire restricted filesystem.
The remediation is straightforward: update Statamic. The patch was released in versions 5.73.6 and 6.2.5. These versions enforce the view permission check on all asset retrieval endpoints.
If you cannot update immediately, you are in a tight spot because this is a logic flaw in the core code, not a configuration issue. You could theoretically implement a WAF rule to block access to /cp/pdfs/* and /cp/thumbnails/* for users who shouldn't have access, but mapping that logic at the edge is complex and error-prone.
Post-Patch Action: Check your access logs for GET requests to /cp/pdfs/ or /cp/svgs/ originating from IP addresses or user accounts that should not have had access to those specific resources. A sudden spike in 403s after patching might indicate someone was relying on this access, or an automated scraper getting blocked.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
Statamic CMS Statamic | < 5.73.6 | 5.73.6 |
Statamic CMS Statamic | >= 6.0.0-alpha.1, < 6.2.5 | 6.2.5 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-862 |
| Attack Vector | Network |
| CVSS | 4.3 (Medium) |
| Authentication | Required (Low Privilege) |
| Impact | Confidentiality Loss |
| Exploit Status | Functional PoC |
The product does not perform an authorization check when an actor attempts to access a resource or perform an action.