From 4e1fb850bc2cff45e61736ab3b503d0bb97c1d62 Mon Sep 17 00:00:00 2001 From: lukinovec Date: Tue, 18 Aug 2026 17:14:42 +0200 Subject: [PATCH] Require a directory boundary when checking that an asset is inside the asset root The resolved path was compared to the asset root using a plain string prefix, so a directory whose name just starts with the asset root's name passed the check. This didn't matter while the asset root was hardcoded to app/public, but $publicDisk lets it be any disk root. --- src/Controllers/TenantAssetController.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Controllers/TenantAssetController.php b/src/Controllers/TenantAssetController.php index 1863c975..48da0b01 100644 --- a/src/Controllers/TenantAssetController.php +++ b/src/Controllers/TenantAssetController.php @@ -112,8 +112,10 @@ class TenantAssetController implements HasMiddleware // User is attempting to access a nonexistent file $this->abortIf($attemptedPath === false, 'Accessing a nonexistent file'); - // User is attempting to access a file outside the $allowedRoot folder - $this->abortIf(! str($attemptedPath)->startsWith($allowedRoot), 'Accessing a file outside the storage root'); + // User is attempting to access a file outside the $allowedRoot folder. + // The trailing separator is needed so that sibling directories that + // start with the same name (e.g. app/public-private) don't pass. + $this->abortIf(! str($attemptedPath)->startsWith(rtrim($allowedRoot, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR), 'Accessing a file outside the storage root'); } /** @return void|never */