Uploads hardening guide

Disable PHP execution in WordPress uploads, safely.

Uploads should contain media, not executable code. On a suitable Apache single-site install, a narrow rule in the uploads directory can limit the impact of a malicious PHP upload.

01Scope the rule to uploads.

Place the hardening file in wp-content/uploads/, not in the WordPress root.

02It is an Apache control.

Nginx and other servers need an equivalent server-level configuration, not this .htaccess file.

03Check multisite first.

Some multisite setups route files through ms-files.php; WordPress warns not to apply this technique there.

What this protects — and what it does not

The rule denies requests for PHP-like files inside the uploads directory. That matters because an attacker who can upload a script needs the web server to execute it before it becomes a working backdoor. Preventing execution in a media-only directory removes one useful path from upload to server-side code execution.

It is defense in depth, not a substitute for updates, least-privilege accounts, a secure upload workflow, and a web application firewall. It also does not scan a file, remove a compromised plugin, or stop PHP elsewhere in WordPress.

1 A file reaches uploads2 A request targets a PHP-like file3 Apache applies the directory rule4 Execution is denied

Decide whether this approach fits your site

EnvironmentUse this .htaccess rule?Why
Apache single siteUsually, after a backup and test.The file can be isolated to wp-content/uploads/, keeping the change narrow.
Nginx or managed platformNo — ask for the server equivalent.Nginx does not read .htaccess files.
Multisite using ms-files.phpDo not add it blindly.WordPress documents an exception because that routing can require PHP handling for uploaded files.
Do not block PHP in the WordPress root.

WordPress itself needs PHP to run. The protection belongs only in a media-only uploads directory, and only after you have confirmed the server and network setup support it.

Apply and test the narrow rule

  1. 01
    Confirm Apache and the uploads path.

    Verify that the server reads .htaccess and that this WordPress installation stores media in its normal wp-content/uploads/ directory.

  2. 02
    Check the multisite exception.

    If this is a network, confirm whether it uses ms-files.php before adding the rule. Use the host or WordPress documentation when uncertain.

  3. 03
    Generate the uploads-only block.

    In the local .htaccess generator, enable “Block PHP execution in uploads” and copy the separate uploads output.

  4. 04
    Create wp-content/uploads/.htaccess.

    Place the copied output in that directory, not in the root file that contains WordPress permalink rules.

  5. 05
    Verify normal media still works.

    Upload an image, open its public URL, and check that legitimate front-end and admin media requests still load. Roll back the small file if they do not.

Quick answers

Does blocking PHP in uploads break normal WordPress images?

It should not: images, PDFs, and other media are not PHP. Still, test a normal upload and its public URL after making the change because hosts and plugins can customize media handling.

Should I put this rule in the root .htaccess file?

No. The rule should be contained in wp-content/uploads/.htaccess so it applies only to a media directory. Blocking PHP at the root would break WordPress.

Can I use this on WordPress multisite?

Not without checking its upload routing. WordPress specifically cautions against this method for multisite configurations that use ms-files.php.

Primary reference: WordPress hardening documentation.