Fix Guide

How to Protect /wp-admin/install.php in WordPress

April 17, 2026

Every WordPress install ships with a file called wp-admin/install.php. On a healthy site it is mostly harmless. WordPress notices that the site is already set up and returns a short "Already Installed" page. But there is a corner case that a lot of site owners underestimate. The moment something goes wrong with the database, that same file turns into a fully working setup wizard. An attacker who stumbles onto it at the right time can reinstall WordPress on top of your domain, point it at a database they control, and walk away with a complete takeover.



This guide explains when install.php is actually dangerous, which security plugins genuinely cover this case (not all of them do, despite what their marketing suggests), and how to block the file properly. That includes the less comfortable situation where you are on a shared host without access to the server config.



When is install.php actually a problem?



If you visit https://yourdomain.com/wp-admin/install.php on a healthy site, WordPress checks whether the wp_options table already contains a siteurl. If yes, it shows the "Already Installed" screen and that is the end of the story. No form, no action, no takeover.



The problem starts the moment WordPress cannot read that value. Typical scenarios:




  • Database credentials in wp-config.php got broken (wrong password after a host migration, mistyped DB name).

  • Someone dropped or truncated the wp_options table, either by accident during a migration or on purpose via an SQL injection in a vulnerable plugin.

  • A failed staging clone left the file system in place but the database empty.

  • The database user lost permissions on specific tables.



In all of those cases the setup wizard becomes available to anyone on the internet. Whoever reaches it first gets to choose the admin username, password and email, and effectively owns the domain. That is why this check exists in InspectWP even though the file is "normal" on every WordPress install.



Which security plugins can actually protect install.php?



This is the part that trips people up, so it is worth being precise. Most people assume that any WordPress security plugin will automatically cover install.php. That is half true. The answer depends entirely on how the plugin loads.



A regular WordPress plugin boots inside WordPress. It needs the database to start. If your DB is broken or empty (which is the only realistic scenario where install.php becomes dangerous), WordPress never boots far enough to load the plugin. The request lands directly at install.php and PHP happily renders the setup wizard. Security plugins that run as normal plugins cannot help in that situation, by definition.



However, several plugins use a PHP mechanism called auto_prepend_file. That setting tells PHP to execute a specific file before any other PHP script on the server. When a security plugin registers itself this way, it runs before wp-config.php, before the database connection is even attempted, and before install.php. It has its own configuration files and, where needed, its own database connection. A broken WordPress installation does not affect it.



Plugins that support this mode (and can therefore protect install.php even when the WordPress database is down):




  • Wordfence in Extended Protection mode (sometimes called Optimized Mode). This is not the default after installation. You have to enable it explicitly in the Wordfence firewall settings. Once active, a file called wordfence-waf.php is placed in the WordPress root and registered via .htaccess, .user.ini or php.ini.

  • NinjaFirewall (WP Edition). Uses auto_prepend_file as its default mode. It is configured that way on install, no extra toggle needed.

  • NinjaFirewall (Pro / Full WAF). Same mechanism, but registered at the server level. Runs completely outside WordPress.

  • BitFire Security. Supports an "Always On Protection" mode, also based on auto_prepend_file. Comparable in behavior to Wordfence Extended Protection.

  • Shield Security (ShieldPRO). Also loads via auto_prepend_file, although it takes a more conservative approach and does not modify .htaccess directly.

  • MalCare. Uses auto_prepend_file as part of its WAF setup.



Plugins that cannot block install.php when WordPress is broken, because they run as normal WordPress plugins:




  • Wordfence in the default Basic Mode (before you enable Extended Protection).

  • Solid Security (formerly iThemes Security). It does not ship a WAF that runs before WordPress.

  • All-In-One WP Security & Firewall. Good at file and login hardening but runs inside WordPress.

  • Most plugin based firewalls that do not rely on auto_prepend_file.



A practical consequence: if you use Wordfence, go into Wordfence, Firewall, Manage WAF, and check whether the message reads "Optimized" or "Extended Protection Enabled". If it still says Basic Mode, the optimization wizard walks you through setting up auto_prepend_file for your server. This single change is what turns Wordfence from a reactive plugin into a genuine pre WordPress firewall.



One caveat for both paths. The mechanism requires that your host actually allows auto_prepend_file via .htaccess, .user.ini or php.ini. On most shared hosts this works out of the box. On some locked down managed hosts the setting is restricted, and the optimization wizard will fail silently or show a warning. In that case you are back to the webserver rule approach described below.



Option 1: Block install.php via .htaccess (Apache)



If your host runs Apache (which is what the majority of shared hosting providers like IONOS, Strato, All-Inkl, Hostinger, DomainFactory, SiteGround, Bluehost use), you can add the following block to the .htaccess file in your WordPress root directory:



<Files "install.php">
  Require all denied
</Files>


This works on Apache 2.4 and above, which is what pretty much every host has been running for years. If you are on something older (Apache 2.2), use the legacy syntax instead:



<Files "install.php">
  Order allow,deny
  Deny from all
</Files>


Place the snippet above the # BEGIN WordPress marker so WordPress's automatic rewrite management does not touch it during updates.



After saving the file, visit https://yourdomain.com/wp-admin/install.php in a private browser window. You should see a 403 Forbidden response. If you still see the "Already Installed" page, .htaccess overrides are disabled on your host. Jump to Option 3.



Option 2: Block install.php via nginx



On nginx there is no .htaccess. If you manage your own server (VPS, dedicated, or a flexible host like Hetzner Cloud), add this inside your site's server block:



location = /wp-admin/install.php {
  deny all;
  return 403;
}


Reload nginx with sudo nginx -t && sudo systemctl reload nginx and test with curl -I https://yourdomain.com/wp-admin/install.php. You should get a 403.



Some managed hosts that use nginx under the hood (like Raidboxes, Kinsta, WP Engine) already ship with this kind of rule. It is worth checking your host's documentation or opening a support ticket. The answer is usually either "already covered" or they add the rule for you.



Option 3: Shared hosting without Apache overrides



If you are on a shared nginx host and .htaccess is ignored, you have fewer options but you are not stuck. In order of preference:




  1. Install one of the pre WordPress firewalls listed above. On shared hosts where auto_prepend_file is allowed, a plugin like NinjaFirewall or Wordfence in Extended Protection mode gives you the same protection as a server rule, without touching any server config. This is often the most pragmatic path.

  2. Ask your host. Most managed WordPress hosts will add a server level rule for you if you ask. It takes them five minutes and they do it routinely.

  3. Replace the file contents. You can open wp-admin/install.php via SFTP and replace the entire file with a single line:
    <?php // intentionally disabled, see install.php.bak

    Keep a backup of the original (install.php.bak) outside the public web root in case you ever legitimately need to reinstall. The downside: WordPress core updates will put the original file back, so you need to reapply the change after every major update. A small must use plugin can automate this (see the related code snippet).

  4. Deny by file permissions. Changing the file mode to 000 via SFTP also blocks access on most hosts. Same caveat: core updates will reset it.



What about renaming or deleting install.php?



Technically you can delete install.php entirely. WordPress does not need it for normal operation. It is only used during the initial setup and for some internal upgrade routines. The catch is that the file is restored with every WordPress core update, so deletion is not a permanent fix. It also occasionally gets referenced by the auto upgrade process, so you may see warnings in your error log if it is missing.



Renaming is even worse. WordPress will not find the file under its new name but will happily recreate the original one during the next update. You end up with two copies.



Blocking access at the webserver level, or via a pre WordPress firewall, is almost always the better answer.



How to verify your setup



After you have applied one of the options above:




  1. Open https://yourdomain.com/wp-admin/install.php in a private or incognito window.

  2. You should see a 403 Forbidden page (or 404 if you removed the file, or the firewall's custom block page if you went the plugin route).

  3. If you see the "Already Installed" page or, much worse, an actual setup form, the rule is not active. Double check the file path, clear any caches (Cloudflare, Varnish, server level page cache), and try again.

  4. Run a fresh InspectWP scan. The "install.php exposed" check in the WordPress section should turn green.



Related checks worth running



While you are locking things down, the same kind of webserver level block (or pre WordPress firewall rule) is worth applying to a few other sensitive endpoints: xmlrpc.php (unless you actively use it), wp-config.php.bak, .git/, .env, and any phpinfo.php files a developer might have left behind. InspectWP flags all of these automatically in its security section.



The install.php case is a good example of defense in depth. WordPress protects itself, a properly configured security plugin adds another layer, and a webserver rule covers the one scenario where both of those can fail. Pick whichever combination matches your host. Five lines of config, or one toggle in a firewall plugin, is enough to close the gap for good.

Check your WordPress site now

InspectWP analyzes your WordPress site for security issues, SEO problems, GDPR compliance, and performance — for free.

Analyze your site free