How to Block PHP Execution in Magento Media Folders
Security Intermediate 5 min read

How to Block PHP Execution in Magento Media Folders

Block PHP execution in Magento media folders with nginx and Apache deny rules so uploaded files cannot run as web shells, then verify the 403.

Published: October 31, 2026 • Updated: October 31, 2026
magentonginxapachehardeningweb shell

To block PHP execution in Magento media folders, deny web access to the upload directories at the web server, before any rule that hands .php requests to PHP-FPM. On nginx that means a location block for pub/media/custom_options/ placed ahead of the PHP handler; on Apache it means an .htaccess file that turns the PHP engine off and denies access. This contains the damage from upload flaws such as PolyShell (CVE-2026-48356), but it does not replace the APSB26-73 patch.

Why block PHP execution in Magento media folders?

Blocking execution means an uploaded script stays a harmless file instead of becoming a web shell. Upload bugs keep recurring in e-commerce platforms, and the web server rule protects you against the next one as well as the current one.

In the PolyShell research, Sansec found that whether an unauthenticated upload became remote code execution depended on the server: nginx setups that pass every .php request to FastCGI, and Apache without PHP execution disabled, were the exposed ones. The Adobe Commerce PolyShell CVE-2026-48356 news coverage has the version details. For why a file that looks like an image can still carry code, see what a polyglot file is and why upload checks miss it.

Before you change anything

Do these first, on a staging copy if you have one:

  1. Take a backup of your current web server configuration files.
  2. Note which web server actually serves the store. Many Magento installs run nginx in front of PHP-FPM. Some run Apache, and some run nginx in front of Apache. The rule has to live on whichever server decides whether PHP runs.
  3. Record your Magento document root. The paths below are relative to the Magento root, as Sansec wrote them. Adjust them if your web root is pub/ itself.
  4. Check the folder for existing files before you lock it, so you know what was there.

Sansec's check for unexpected files:

find pub/media/custom_options/ -type f ! -name '.htaccess'

Any .php, .phtml or .phar file in that folder is a strong indicator of compromise. If you find one, stop and treat it as an incident, not a configuration task.

How do you block the upload folder on nginx?

On nginx you add a location block that denies every request to the custom options folder and place it before any location block that matches .php. Order matters because nginx evaluates regex locations in the order they appear and uses the first match.

The block Sansec published:

location ~* ^/pub/media/custom_options/ {
    deny all;
    return 403;
}

Steps:

  1. Open the server block that serves your store. On many installs this includes the Magento sample nginx config, so the PHP handler may be in an included file rather than the main one.
  2. Add the block above the first location block that matches PHP files, including any that come from an include.
  3. Test the configuration and reload nginx only if the test passes.
  4. Request any file under /pub/media/custom_options/ from a browser or an external host and confirm you get a 403 response.

If your web root is the pub/ directory, the public URL path will be /media/custom_options/ instead. Match the path that appears in the browser, not the path on disk.

How do you block the upload folder on Apache?

On Apache you confirm that an .htaccess file exists in the custom options folder and that it switches off the PHP engine and denies all access. Apache applies .htaccess rules per directory, so the file must sit in the folder itself.

Sansec says the file at pub/media/custom_options/.htaccess should contain:

<IfModule mod_php.c>
    php_flag engine 0
</IfModule>
Deny from all

Steps:

  1. Check that the file exists and matches the content above.
  2. Confirm Apache is configured to honor .htaccess files for the media path. If overrides are disabled there, the file is ignored.
  3. If Apache uses a non-default AccessFileName, rename the file to match, as Sansec notes.
  4. Request a file in the folder from outside and confirm the 403.

The php_flag line only applies when PHP runs as an Apache module. If Apache passes PHP to PHP-FPM, the deny line is what protects you, so do not remove it.

Other folders to review

The custom options folder is the one PolyShell writes to, but it is not the only place uploads land. Sansec's October 2026 report on a CMS block skimming campaign also flags unexpected files in pub/media/customer_address/. Review every folder under pub/media/ that accepts user content and apply the same deny rule where the storefront does not need to serve files directly.

Where the storefront does need to serve images from a folder, deny script execution only. Make sure no PHP handler matches that path, and keep the folder writable only by the account that needs it.

How do you check the rule is still in place later?

Re-test the block after every web server change, Magento upgrade or hosting migration, because new includes and sample configs can reorder location blocks. A one-line check in your deployment or monitoring that requests a file from the folder and expects a 403 catches regressions.

Pair it with a scheduled search for the backdoor name Sansec linked to the PolyShell waves:

find /var/www -name 'accesson.php' -type f

Adjust /var/www to your document root.

What this does not fix

The web server rule stops uploaded files from running or being served. It does not stop the upload. Sansec is explicit that blocking web access to the folder alone does not prevent uploads, and the file stays on disk. You still need the APSB26-73 fix, and if your store is behind on patch levels, read why Magento isolated patches need the latest patch level before you schedule it.

If you found files, also check the cms_block and cms_page tables for injected scripts and review admin accounts. An attacker who already ran code may have left persistence outside the upload folder, and the web shell explainer covers where that tends to hide.