Feb 12, 2026·6 min read·18 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.
A property shadowing vulnerability exists in protobufjs where schema-derived names can collide with and overwrite runtime-critical internal helper properties. This issue leads to uncaught runtime exceptions and crash-based Denial of Service.
An integer truncation vulnerability (CWE-197) exists in SQLite before version 3.50.2 during the processing of aggregate queries with more than 32,767 distinct column references. This causes an internal 32-bit counter to truncate to a signed 16-bit integer, producing negative values that cause out-of-bounds heap operations in release builds.
An integer overflow vulnerability in the Windows kernel-mode HTTP driver (HTTP.sys) allows an unauthenticated remote attacker to execute arbitrary code with kernel privileges or cause a Denial of Service via a specially crafted sequence of HTTP request headers.
A memory corruption vulnerability exists in the FTS5 (Full-Text Search 5) extension of SQLite prior to version 3.53.2. An attacker can construct a malicious database file containing corrupt FTS5 page data. Querying this database triggers out-of-bounds reads and heap-based buffer overflows, potentially causing a crash or arbitrary code execution.
A mass assignment vulnerability (CWE-915) in n8n's self-service settings API endpoint (PATCH /me/settings) allows authenticated Single Sign-On (SSO) users to disable SSO enforcement for their accounts by injecting administrative parameters. This bypasses organizational identity provider controls and multi-factor authentication (MFA).
CVE-2026-55699 (also identified as GHSA-4gxm-v5v7-fqc4) is a critical path traversal and arbitrary directory deletion vulnerability in the pnpm package manager. The issue exists because the manifest validation process fails to prevent relative path segments within the package 'bin' keys. When a malicious package containing structured path traversal markers is globally installed and later manipulated, pnpm resolves the target paths through path.join() and passes the resolved paths to a recursive deletion function, resulting in arbitrary directory removal.