October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsWindows FixRecommendedWindows errors stealing your time? Find the fix fastScan stability, cleanup and performance issues.Fix NowOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
VGSources
Blog

How to Secure the WordPress Uploads Directory Without Breaking Media

Prevent uploaded scripts from running in WordPress without breaking media delivery. This guide covers Nginx, Apache/LiteSpeed, multisite paths, permissions, verification and troubleshooting.
Length9 min Posted Quest giverVGSources Team

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

To secure /wp-content/uploads, keep the directory readable over HTTP(S) and writable by WordPress, but deny PHP execution inside it at the web-server layer. On Nginx, add a location rule in the server configuration. On Apache or LiteSpeed, use a .htaccess or virtual-host rule. Then verify that a harmless PHP test file is denied while JPG, PNG, PDF and other legitimate media still load.

What the uploads directory does—and what security must preserve

WordPress normally stores uploaded images, videos, documents and generated media variants under /wp-content/uploads, often separated into year-and-month folders. Browsers need to request those files directly, so making the entire directory inaccessible will break images, downloads, thumbnails, feeds and editor previews.

As an Amazon Associate I earn from qualifying purchases.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

WordPress also needs a server-side process with write access there when an administrator or editor uploads media. Those two requirements are different from PHP execution. A process may be allowed to create a file while the web server refuses to execute a PHP request for that file. The useful security boundary is therefore: deliver ordinary media, permit the expected write operation, and reject script execution.

An uploaded PHP file is dangerous because a successful request can run code with the privileges of the web process. Blocking execution in the upload location limits the damage from a vulnerable plugin, a compromised account or an upload validation bypass. This control does not replace patching or account security; it removes one particularly valuable execution path.

Choose the rule for the server actually serving the site

Server Where the control belongs Normal media behavior Access normally required Multisite consideration
Nginx Relevant server configuration, usually a server block or included configuration file Files such as JPG, PNG, PDF and video remain available unless another rule blocks them Permission to edit server configuration and reload or restart Nginx, or a host that will apply the change Cover both uploads and the documented files path where the installation uses it
Apache An .htaccess file in the uploads directory or the applicable virtual-host configuration Only PHP requests are denied by the shown rule; ordinary media is unaffected Permission to use per-directory overrides, or virtual-host access if overrides are restricted Check the network’s upload and rewrite layout before applying a blanket path rule
LiteSpeed Usually Apache-compatible .htaccess controls, subject to the host’s configuration Expected media should continue to load Ability to edit the applicable file and confirm which directives the host permits Confirm the host’s mapping for multisite files and uploads
IIS or another server The server’s own request-filtering or handler configuration Must be tested rather than assumed Server or hosting-panel access, or help from the host Use the site’s actual URL-to-file mapping

Nginx has no directory-level file equivalent to Apache’s .htaccess. WordPress’s Advanced Administration Handbook states: “With Nginx there is no directory-level configuration file like Apache’s .htaccess or IIS’s web.config files.” A rule pasted into an uploads .htaccess file therefore has no effect on an Nginx site.

Identify the real uploads path before editing anything

  1. Confirm the document root. The public directory may be named public_html, www, htdocs or something else. The filesystem path is not necessarily the same as the URL path.
  2. Check WordPress’s media settings. A standard installation uses /wp-content/uploads, but a multisite network or a media-storage plugin can use a different location or URL.
  3. Determine the web server. Ask the host or inspect the hosting control panel. Do not select an Nginx rule merely because an Apache-style file exists in the project.
  4. Record ownership and permissions. Note which user owns the directory and which account runs PHP. This information is needed if uploads stop working after a permissions change.
  5. Make a recoverable copy of the file you will edit. Save the current server block or .htaccess contents outside the web root before changing it.

If the site uses custom storage, the correct protection target is the directory that is both publicly mapped and capable of receiving untrusted uploads. Protecting an unused default folder does not secure the active storage location.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Block PHP execution on Nginx

Add the rule to the server configuration

Place this location block in the Nginx configuration that handles the WordPress site:

location ~* /(?:uploads|files)/.*.php$ {
    deny all;
}

The expression matches PHP requests below paths containing uploads or files, and deny all prevents the request from being served. The inclusion of files matters for WordPress multisite configurations that use that path. Apply the rule in the relevant server context rather than in an uploads directory.

Deploy without losing the existing WordPress configuration

  1. Open the active server block or included site configuration, not an unused example file.
  2. Insert the location rule at the server-configuration level used by the site’s existing WordPress rules.
  3. Run the host’s configuration validation command or use its control-panel test before reloading. The exact command and reload method vary by host, so follow that host’s documented procedure.
  4. Reload Nginx only after validation succeeds. A syntax error can prevent the server from reloading and may take the site offline until the configuration is corrected.
  5. Perform the functional test described below from an external HTTP(S) request.

Do not try to solve this with an uploads .htaccess file on Nginx; Nginx does not read it for directory access control.

Check multisite and rewrite interactions

Network installations can use different URL forms for uploaded files, and WordPress documents separate rewrite and server-configuration models for multisite. Verify an actual media URL from each relevant site and test the path used for network files. A rule that protects only the single-site uploads pattern may leave a network-specific files path uncovered; the example above includes both names for that reason.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Block PHP execution with Apache or LiteSpeed

Use an uploads-directory .htaccess file

In Apache-compatible hosting, create or edit the .htaccess file in the uploads directory and add:

<FilesMatch "\.php$">
    Require all denied
</FilesMatch>

This denies requests for files whose names end in .php within the directory governed by the file. It does not deny JPG, PNG, PDF, audio, video or other non-PHP media. The host must permit the FilesMatch and Require directives in per-directory overrides; some managed environments disable them.

Keep custom rules outside WordPress’s generated block

If you place the protection in the site’s main .htaccess file, keep it outside the # BEGIN WordPress and # END WordPress section. WordPress may regenerate that section when permalink settings are saved, overwriting edits made inside it. An uploads-directory file is easier to isolate, while a virtual-host rule is preferable when the host restricts .htaccess overrides.

Confirm the Apache version and host policy

The shown syntax uses Apache’s authorization directive style. Older or specially configured servers may require a host-specific equivalent. Ask the host which directives are allowed rather than substituting a rule copied from an unrelated Apache version. LiteSpeed commonly accepts Apache-style controls, but the active configuration still determines the result.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Verify that the control works

A configuration change is not complete until it has been tested from the same HTTP(S) path an attacker would use.

  1. Identify the active path. Use the real document root and URL mapping, including a multisite or custom-storage variation.
  2. Create a harmless test file. In the protected directory, create security-test.php containing only plain text, such as uploads execution test. Do not place credentials, shell commands or diagnostic code in it.
  3. Request the file over HTTP(S). Visit its complete URL in a browser or use an HTTP client from outside the server.
  4. Confirm execution is denied. A 403 or 404 response is an expected successful outcome. The browser must not display the file’s PHP output, and the server must not process it as a script.
  5. Test representative media. Open a JPG or PNG, a PDF if the site serves documents, and a normal video or audio URL when those media types are part of the site.
  6. Remove the test file immediately. Leaving even harmless executable-looking files in a public directory creates confusion during later audits.
  7. Inspect the directory and logs. Look for unexpected executable files, ownership changes and repeated denied requests. Re-test after a hosting migration, PHP change, web-server change or cache configuration change.

If the PHP file returns its source code, downloads, displays a PHP-generated response or otherwise executes, the rule is not active at the request path being tested. Stop treating the directory as protected until the server configuration is corrected.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Keep uploads writable without making them unsafe

Use least-privilege permissions

Do not set the uploads tree to world-writable 777 as a troubleshooting shortcut. WordPress’s hardening and permissions guidance treats broadly writable locations as an attack surface. Set ownership and write permissions so the PHP process can create the files WordPress needs, while unrelated users cannot modify the tree.

Permission numbers alone do not explain every hosting setup. Shared hosting, PHP-FPM pools, containers and deployment accounts can use different users and groups. If uploads fail after tightening permissions, check the PHP process’s effective user, directory traversal permissions on parent folders and the ownership of existing year/month directories. Correct the ownership or group arrangement instead of reopening the directory to everyone.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Separate execution control from file validation

The web-server rule is a backstop, not permission to accept arbitrary uploads. WordPress, its plugins and any custom upload endpoint should still validate file types, enforce authentication and limit who can upload. Review whether a plugin writes files outside the normal uploads tree; that location needs equivalent protection if it is publicly reachable.

Add defense in depth around the execution rule

  • Update WordPress core, themes and plugins. Remove abandoned or unused plugins rather than leaving their code reachable.
  • Disable dashboard file editing when appropriate. Setting DISALLOW_FILE_EDIT in wp-config.php removes the built-in editor for themes and plugins. It does not replace upload-directory protection.
  • Use non-privileged service accounts. Run the site and web server with the least privilege compatible with the hosting model.
  • Consider a security plugin, reverse-proxy WAF or hosting firewall. These layers can detect malicious requests and abuse, but they do not replace denying PHP execution in uploads.
  • Review logs and unexpected files. A newly appearing executable file, repeated requests for PHP under uploads or unexplained permission changes warrants investigation.

Defense in depth reduces the chance that one missed update, credential compromise or configuration mistake becomes arbitrary code execution. Each layer has a different job; none makes the others unnecessary.

Troubleshoot common failures

Symptom Likely cause What to check
PHP test file executes The rule is in the wrong server, wrong path or an inactive configuration file Confirm the active document root, virtual host and server type; reload the configuration and inspect the response again
Images and PDFs return 403 A broader deny rule or directory restriction is blocking all files Check for a parent-directory authorization rule and narrow the control to PHP requests
New uploads fail in WordPress Filesystem ownership or write permission was changed Check the PHP process user, group membership and parent-directory traversal permissions; do not use 777 as the default fix
Apache rule has no effect Overrides are disabled, or the file is not in the directory serving the URL Ask the host whether FilesMatch and Require are permitted and verify the URL-to-filesystem mapping
Nginx rule has no effect The rule was put in .htaccess or an unused server block Move it to the active Nginx server configuration, validate it and reload Nginx
One multisite site’s files remain executable The network uses a different files or upload URL pattern Capture a real URL from that site and extend the server rule only after confirming the mapping
Media works in a browser but fails through a cache or CDN A proxy or cache has its own access rule or stale response Test the origin and public URL separately, purge the relevant cache and retain the origin execution denial

Operational checklist

  • Document the actual public uploads path and any custom or multisite storage paths.
  • Record whether the site runs Apache, LiteSpeed, Nginx or IIS before selecting a directive.
  • Back up the configuration file, then add the narrow PHP-denial rule at the correct server layer.
  • Validate and reload the server according to the host’s procedure.
  • Request a harmless PHP file and confirm a 403 or 404 rather than execution.
  • Open representative images, documents and other required media.
  • Delete the test file and inspect the directory for unexpected executables.
  • Review ownership and permissions, keeping write access limited to the accounts that need it.
  • Repeat the test after migrations, PHP or web-server upgrades, hosting changes and significant caching changes.

Key decision

The highest-value change is simple: disable PHP execution in every publicly reachable upload location while leaving ordinary media delivery intact. Nginx requires a server-level location rule; Apache and compatible LiteSpeed deployments can usually use a narrowly scoped .htaccess or virtual-host rule. The protection is credible only when a real HTTP test proves the PHP file is denied and normal media still works.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More quests from Patch Notes

  1. How to Set Up a RedM (RDR2) Server in 2026: License Key, txAdmin and server.cfg, Step by StepBlog11min
  2. Best RedM (RDR2) Server Hosting in 2026: Comparing Four Hosts on Slots, Memory and PriceBlog10min
  3. How to Host a Mindustry Server in 2026: server-release.jar, Port 6567 and the Commands That MatterBlog7min
Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Outdated Drivers Are Slowing You DownFree scan - exact matches

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.