VYPR
Moderate severityNVD Advisory· Published Feb 11, 2026· Updated Feb 12, 2026

Statamic's missing authorization allows access to assets

CVE-2026-25633

Description

Statamic is a, Laravel + Git powered CMS designed for building websites. Prior to 5.73.6 and 6.2.5, users without permission to view assets are able are able to download them and view their metadata. Logged-out users and users without permission to access the control panel are unable to take advantage of this. This has been fixed in 5.73.6 and 6.2.5.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

In Statamic CMS, a missing authorization check allowed authenticated users with no asset permissions to download assets or view their metadata.

Vulnerability

Overview

CVE-2026-25633 affects Statamic CMS, a Laravel and Git powered CMS. Prior to versions 5.73.6.2.5 and 5.73.6, the application failed to enforce authorization checks on certain asset-related controllers, specifically the PdfController::show, AssetController::show, and FoldersController::update methods [1]. This allowed users who were authenticated into the control panel but did not have the necessary 'view' permission for assets to still download asset files and access their metadata. The issue was introduced because authorization was either missing or placed after potentially sensitive operations [1].

Exploitation

Conditions

The vulnerability is only exploitable by users who are logged in and have access to the Statamic control panel; logged-out-of-the-box, these users do not need any specific 'view assets' permission [2]. Logged-out users and users without control panel access cannot take advantage of this weakness [2]. The attack surface includes direct routes to asset downloads (such as PDF assets) and folder operations, where the systems did not call `$this case authorization before returning file contents [1].

Impact

An authenticated attacker who lacks explicit asset permissions can download arbitrary assets from the CMS and view their metadata [2]. This could lead to unauthorized disclosure of sensitive files stored in asset containers, potentially including documents, images, or other uploaded content that should be restricted to authorized users only [1].

Mitigation

The vulnerability has been fixed in Statamic versions 5.73.6.2.5 and 5.73.6 [2]. The fix involves adding explicit $this->authorize('view', $asset) calls in the affected controllers before returning asset data [1]. Users are strongly advised to update to these patched versions 5.73.6 or later (for the 5.x branch) or to version in the 6.x branch [4]. There is no workaround mentioned; the most effective mitigation is applying the update.

AI Insight generated on May 19, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
statamic/cmsPackagist
< 5.73.65.73.6
statamic/cmsPackagist
>= 6.0.0-alpha.1, < 6.2.56.2.5

Affected products

2

Patches

1
5a6f47246edf

[5.x] Asset auth fix (#13883)

https://github.com/statamic/cmsDuncan McCleanFeb 10, 2026via ghsa
8 files changed · +262 12
  • routes/cp.php+0 1 modified
    @@ -229,7 +229,6 @@
     
         Route::resource('asset-containers', AssetContainersController::class);
         Route::post('asset-containers/{asset_container}/folders', [FoldersController::class, 'store']);
    -    Route::patch('asset-containers/{asset_container}/folders/{path}', [FoldersController::class, 'update'])->where('path', '.*');
         Route::get('asset-containers/{asset_container}/blueprint', [AssetContainerBlueprintController::class, 'edit'])->name('asset-containers.blueprint.edit');
         Route::patch('asset-containers/{asset_container}/blueprint', [AssetContainerBlueprintController::class, 'update'])->name('asset-containers.blueprint.update');
         Route::post('assets/actions', [AssetActionController::class, 'run'])->name('assets.actions.run');
    
  • src/Http/Controllers/CP/Assets/FoldersController.php+0 5 modified
    @@ -37,9 +37,4 @@ public function store(Request $request, $container)
     
             return $container->assetFolder($path)->save();
         }
    -
    -    public function update(Request $request, $container, $folder)
    -    {
    -        return $container->assetFolder($folder)->save();
    -    }
     }
    
  • src/Http/Controllers/CP/Assets/PdfController.php+5 3 modified
    @@ -15,9 +15,11 @@ class PdfController extends Controller
          */
         public function show($encodedAssetId)
         {
    -        if (! $contents = $this->asset($encodedAssetId)->contents()) {
    -            abort(500);
    -        }
    +        $asset = $this->asset($encodedAssetId);
    +
    +        abort_if(! $contents = $asset->contents(), 500);
    +
    +        $this->authorize('view', $asset);
     
             return response($contents)->header('Content-Type', 'application/pdf');
         }
    
  • src/Http/Controllers/CP/Assets/SvgController.php+3 3 modified
    @@ -17,9 +17,9 @@ public function show($asset)
         {
             $asset = $this->asset($asset);
     
    -        if (! $contents = $asset->disk()->get($asset->path())) {
    -            abort(500);
    -        }
    +        abort_if(! $contents = $asset->disk()->get($asset->path()), 500);
    +
    +        $this->authorize('view', $asset);
     
             return response($contents)->header('Content-Type', 'image/svg+xml');
         }
    
  • src/Http/Controllers/CP/Assets/ThumbnailController.php+2 0 modified
    @@ -65,6 +65,8 @@ public function show($asset, $size = null, $orientation = null)
             $this->orientation = $orientation;
             $this->asset = $this->asset($asset);
     
    +        $this->authorize('view', $this->asset);
    +
             if ($placeholder = $this->getPlaceholderResponse()) {
                 return $placeholder;
             }
    
  • tests/Feature/Assets/ImageThumbnailTest.php+84 0 added
    @@ -0,0 +1,84 @@
    +<?php
    +
    +namespace Feature\Assets;
    +
    +use Illuminate\Http\UploadedFile;
    +use PHPUnit\Framework\Attributes\Test;
    +use Statamic\Facades\AssetContainer;
    +use Statamic\Facades\User;
    +use Tests\FakesRoles;
    +use Tests\PreventSavingStacheItemsToDisk;
    +use Tests\TestCase;
    +
    +class ImageThumbnailTest extends TestCase
    +{
    +    use FakesRoles;
    +    use PreventSavingStacheItemsToDisk;
    +
    +    private $tempDir;
    +
    +    public function setUp(): void
    +    {
    +        parent::setUp();
    +
    +        config(['filesystems.disks.test' => [
    +            'driver' => 'local',
    +            'root' => $this->tempDir = __DIR__.'/tmp',
    +        ]]);
    +    }
    +
    +    public function tearDown(): void
    +    {
    +        app('files')->deleteDirectory($this->tempDir);
    +
    +        parent::tearDown();
    +    }
    +
    +    #[Test]
    +    public function it_returns_thumbnail()
    +    {
    +        $container = AssetContainer::make('test')->disk('test')->save();
    +        $container
    +            ->makeAsset('one.png')
    +            ->upload(UploadedFile::fake()->image('one.png'));
    +
    +        $this->setTestRoles(['test' => ['access cp', 'view test assets']]);
    +        $user = User::make()->assignRole('test')->save();
    +
    +        $this
    +            ->actingAs($user)
    +            ->getJson('/cp/thumbnails/'.base64_encode('test::one.png'))
    +            ->assertSuccessful();
    +    }
    +
    +    #[Test]
    +    public function it_404s_when_the_asset_doesnt_exist()
    +    {
    +        $container = AssetContainer::make('test')->disk('test')->save();
    +
    +        $this->setTestRoles(['test' => ['access cp', 'view test assets']]);
    +        $user = User::make()->assignRole('test')->save();
    +
    +        $this
    +            ->actingAs($user)
    +            ->getJson('/cp/thumbnails/'.base64_encode('test::unknown.png'))
    +            ->assertNotFound();
    +    }
    +
    +    #[Test]
    +    public function it_denies_access_without_permission_to_view_asset()
    +    {
    +        $container = AssetContainer::make('test')->disk('test')->save();
    +        $container
    +            ->makeAsset('one.png')
    +            ->upload(UploadedFile::fake()->image('one.png'));
    +
    +        $this->setTestRoles(['test' => ['access cp']]);
    +        $user = User::make()->assignRole('test')->save();
    +
    +        $this
    +            ->actingAs($user)
    +            ->getJson('/cp/thumbnails/'.base64_encode('test::one.png'))
    +            ->assertForbidden();
    +    }
    +}
    
  • tests/Feature/Assets/PdfThumbnailTest.php+84 0 added
    @@ -0,0 +1,84 @@
    +<?php
    +
    +namespace Feature\Assets;
    +
    +use Illuminate\Http\UploadedFile;
    +use PHPUnit\Framework\Attributes\Test;
    +use Statamic\Facades\AssetContainer;
    +use Statamic\Facades\User;
    +use Tests\FakesRoles;
    +use Tests\PreventSavingStacheItemsToDisk;
    +use Tests\TestCase;
    +
    +class PdfThumbnailTest extends TestCase
    +{
    +    use FakesRoles;
    +    use PreventSavingStacheItemsToDisk;
    +
    +    private $tempDir;
    +
    +    public function setUp(): void
    +    {
    +        parent::setUp();
    +
    +        config(['filesystems.disks.test' => [
    +            'driver' => 'local',
    +            'root' => $this->tempDir = __DIR__.'/tmp',
    +        ]]);
    +    }
    +
    +    public function tearDown(): void
    +    {
    +        app('files')->deleteDirectory($this->tempDir);
    +
    +        parent::tearDown();
    +    }
    +
    +    #[Test]
    +    public function it_returns_thumbnail()
    +    {
    +        $container = AssetContainer::make('test')->disk('test')->save();
    +        $container
    +            ->makeAsset('one.pdf')
    +            ->upload(UploadedFile::fake()->createWithContent('one.pdf', ' '));
    +
    +        $this->setTestRoles(['test' => ['access cp', 'view test assets']]);
    +        $user = User::make()->assignRole('test')->save();
    +
    +        $this
    +            ->actingAs($user)
    +            ->getJson('/cp/pdfs/'.base64_encode('test::one.pdf'))
    +            ->assertSuccessful();
    +    }
    +
    +    #[Test]
    +    public function it_404s_when_the_asset_doesnt_exist()
    +    {
    +        $container = AssetContainer::make('test')->disk('test')->save();
    +
    +        $this->setTestRoles(['test' => ['access cp', 'view test assets']]);
    +        $user = User::make()->assignRole('test')->save();
    +
    +        $this
    +            ->actingAs($user)
    +            ->getJson('/cp/pdfs/'.base64_encode('test::unknown.pdf'))
    +            ->assertNotFound();
    +    }
    +
    +    #[Test]
    +    public function it_denies_access_without_permission_to_view_asset()
    +    {
    +        $container = AssetContainer::make('test')->disk('test')->save();
    +        $container
    +            ->makeAsset('one.pdf')
    +            ->upload(UploadedFile::fake()->createWithContent('one.pdf', ' '));
    +
    +        $this->setTestRoles(['test' => ['access cp']]);
    +        $user = User::make()->assignRole('test')->save();
    +
    +        $this
    +            ->actingAs($user)
    +            ->getJson('/cp/pdfs/'.base64_encode('test::one.pdf'))
    +            ->assertForbidden();
    +    }
    +}
    
  • tests/Feature/Assets/SvgThumbnailTest.php+84 0 added
    @@ -0,0 +1,84 @@
    +<?php
    +
    +namespace Feature\Assets;
    +
    +use Illuminate\Http\UploadedFile;
    +use PHPUnit\Framework\Attributes\Test;
    +use Statamic\Facades\AssetContainer;
    +use Statamic\Facades\User;
    +use Tests\FakesRoles;
    +use Tests\PreventSavingStacheItemsToDisk;
    +use Tests\TestCase;
    +
    +class SvgThumbnailTest extends TestCase
    +{
    +    use FakesRoles;
    +    use PreventSavingStacheItemsToDisk;
    +
    +    private $tempDir;
    +
    +    public function setUp(): void
    +    {
    +        parent::setUp();
    +
    +        config(['filesystems.disks.test' => [
    +            'driver' => 'local',
    +            'root' => $this->tempDir = __DIR__.'/tmp',
    +        ]]);
    +    }
    +
    +    public function tearDown(): void
    +    {
    +        app('files')->deleteDirectory($this->tempDir);
    +
    +        parent::tearDown();
    +    }
    +
    +    #[Test]
    +    public function it_returns_thumbnail()
    +    {
    +        $container = AssetContainer::make('test')->disk('test')->save();
    +        $container
    +            ->makeAsset('one.png')
    +            ->upload(UploadedFile::fake()->createWithContent('one.svg', '<svg></svg>'));
    +
    +        $this->setTestRoles(['test' => ['access cp', 'view test assets']]);
    +        $user = User::make()->assignRole('test')->save();
    +
    +        $this
    +            ->actingAs($user)
    +            ->getJson('/cp/svgs/'.base64_encode('test::one.svg'))
    +            ->assertSuccessful();
    +    }
    +
    +    #[Test]
    +    public function it_404s_when_the_asset_doesnt_exist()
    +    {
    +        $container = AssetContainer::make('test')->disk('test')->save();
    +
    +        $this->setTestRoles(['test' => ['access cp', 'view test assets']]);
    +        $user = User::make()->assignRole('test')->save();
    +
    +        $this
    +            ->actingAs($user)
    +            ->getJson('/cp/svgs/'.base64_encode('test::unknown.svg'))
    +            ->assertNotFound();
    +    }
    +
    +    #[Test]
    +    public function it_denies_access_without_permission_to_view_asset()
    +    {
    +        $container = AssetContainer::make('test')->disk('test')->save();
    +        $container
    +            ->makeAsset('one.svg')
    +            ->upload(UploadedFile::fake()->createWithContent('one.svg', '<svg></svg>'));
    +
    +        $this->setTestRoles(['test' => ['access cp']]);
    +        $user = User::make()->assignRole('test')->save();
    +
    +        $this
    +            ->actingAs($user)
    +            ->getJson('/cp/svgs/'.base64_encode('test::one.svg'))
    +            ->assertForbidden();
    +    }
    +}
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

7

News mentions

0

No linked articles in our index yet.