Skip to content

fix: whitelist the admin/logo media prefix so the logos load with remote storage - #5

Open
paales wants to merge 1 commit into
element119:masterfrom
paales:fix/remote-storage-media-whitelist
Open

fix: whitelist the admin/logo media prefix so the logos load with remote storage#5
paales wants to merge 1 commit into
element119:masterfrom
paales:fix/remote-storage-media-whitelist

Conversation

@paales

@paales paales commented Jul 30, 2026

Copy link
Copy Markdown

Written by Claude Code:

Problem

On an installation with remote storage enabled (S3/Azure/GCS), both admin logos upload fine but cannot be displayed.

The upload half is already remote-storage-safe — Magento_RemoteStorage prefers Magento\Framework\Filesystem to customRemoteFilesystem (which covers DirectoryList::MEDIA) and Magento\Framework\File\Uploader to Magento\RemoteStorage\Model\File\Uploader — so the file lands in the bucket and core_config_data gets the bare basename, exactly as intended.

Serving it is where it breaks. HeaderPlugin renders <media base url>/admin/logo/custom/login/<file>. That path does not exist on the web server's filesystem, so nginx's try_files $uri $uri/ /get.php$is_args$args falls through to pub/get.php. get.php — and Magento\MediaStorage\App\Media behind it — serves only paths whose prefix is listed in system/media_storage_configuration/allowed_resources. Core ships catalog, wysiwyg, logo, tmp, … but nothing that matches admin/…, so isAllowed() returns false and both logos hard-404 while the files sit happily in the bucket.

Note logo is on the core list, but the check is stripos($resource, $allowedResource) === 0 — for admin/logo/custom/login/x.png that returns 6, not 0, so it does not match.

Fix

Register the admin/logo prefix from the module's own etc/config.xml. Because the check is a prefix match, one entry covers both custom/login and custom/menu and nothing else under media/admin/.

The entry is inert on a local filesystem — the web server serves those paths directly and get.php is never reached — so this is safe for every installation, not just remote-storage ones.

Verification

Magento 2.4.9 / Mage-OS 3.2.0, remote_storage.driver = aws-s3 (OVH S3), logos uploaded through the admin:

URL before after
/media/admin/logo/custom/login/logo-horizontal.png 404 200 image/png
/media/admin/logo/custom/menu/logo-vertical.png 404 200 image/png

Confirmed on every web pod after a rollout, with no other changes in play.

One caveat worth knowing when testing: pub/get.php caches the whitelist in var/resource_config.json for system/media_storage_configuration/configuration_update_time seconds (3600 by default), and cache:flush does not touch that file — so an already-warm node can keep 404ing until it expires or the file is removed.

Also added a short Remote Storage section to the README.

Both logos upload correctly with remote storage enabled -- the file lands in
the bucket and core_config_data stores the basename -- but they cannot be
served.

HeaderPlugin renders <media base url>/admin/logo/custom/{login,menu}/<file>.
With remote storage that path does not exist on the web server's filesystem,
so nginx/Apache falls through to pub/get.php. Magento\MediaStorage\App\Media
serves only paths whose prefix appears in
system/media_storage_configuration/allowed_resources; core ships catalog,
wysiwyg, logo, tmp and friends, but nothing matching admin/... The result is a
hard 404 on both logos while the files sit happily in the bucket.

Register the admin/logo prefix from the module's own config.xml. The whitelist
is prefix-matched with stripos($resource, $allowed) === 0, so a single entry
covers both custom/login and custom/menu and nothing else under media/admin/.

Inert on a local filesystem: the web server serves those paths directly and
get.php is never reached.

Verified on Magento 2.4.9 / Mage-OS 3.2.0 with remote_storage.driver=aws-s3
(OVH S3): both logo URLs go from 404 to 200 image/png with this change.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant