WordPress install or upgrade script reachable

The WordPress installer or database upgrader answers with its setup page instead of 'already installed'. On an unconfigured or half-migrated site anyone who finds it can complete the installation with their own administrator account and own the server.

Do this: Delete or block wp-admin/install.php and upgrade.php. A reachable install script can let an attacker reconfigure the site against their own database.
PassThe installer and upgrader report the site as already installed, or the site is not WordPress.
CriticalThe WordPress installer or upgrader is reachable and not marked as already installed.

The fix, in one snippet

Example to adapt nginx
location ~* /wp-admin/(install|upgrade)\.php { deny all; return 404; }

Illustrative values. Change the paths, hostnames and options to match your own site before using it.

The sections below explain what is tested, why it matters and the alternatives.

What we test

Scan.now sends GET /wp-admin/install.php and GET /wp-admin/upgrade.php and classifies the pages by their content, not their status code (both return 200 either way). On a healthy site install.php answers "You appear to have already installed WordPress" and upgrade.php answers "No Update Required". The finding fires when install.php instead shows the language selector or the "Welcome" form asking for a site title, username and password, or redirects to setup-config.php asking for database credentials. It is also noted when upgrade.php offers the "Update WordPress Database" button to an anonymous visitor, which happens between a core file update and the first administrator login. Scan.now never submits either form and never follows the installer beyond the first page. Rated critical because a live installer needs no vulnerability at all: it is the application offering to hand over administration.

Why it matters

WordPress trusts whoever reaches the installer first. If wp-config.php exists and points at an empty database, the visitor fills in the form and becomes administrator. If wp-config.php is missing, setup-config.php asks for database details, and an attacker can supply a database server they control, complete the install, and then upload a plugin containing PHP: that is code execution on your host, using your web server's credentials and network position, with no bug required. This is how forgotten copies get exploited: a /old/, /new/, /staging/ or /backup/ directory left on the server, a migration where the files were copied before the database, or a site whose database was dropped while the files stayed up. Automated scanners request /wp-admin/setup-config.php and /wp-admin/install.php continuously, so the window between "copied the files" and "finished the install" is measured in minutes, not days. The upgrader is a smaller concern: an anonymous visitor can only trigger the routine database upgrade, but it should still be an administrator's action. The WordPress scanning guide lists this with the other leftover-file exposures.

How to fix it

Close the window immediately: either finish the installation yourself with a strong administrator password, or delete the unfinished copy. If it has been reachable for any length of time, assume someone else may have installed first and check before trusting it:

wp core is-installed && wp user list --role=administrator
find . -newer wp-config.php -name '*.php' -path '*/uploads/*'

Remove stale copies of WordPress from the web root, and rotate database credentials that a stray wp-config.php may have exposed. For staging and in-progress migrations, restrict the setup scripts to your own addresses so a future copy is never public. nginx:

location ~* ^/wp-admin/(install|upgrade|setup-config)\.php$ {
    allow 203.0.113.10;     # your office or VPN address
    deny all;
}

Apache 2.4:

<FilesMatch "^(install|upgrade|setup-config)\.php$">
    Require ip 203.0.113.10
</FilesMatch>

Keep upgrade.php reachable from those addresses rather than blocking it outright, because WordPress redirects administrators to it after a core update that changes the database schema. Once the site is installed and the rules are in place, re-run the WordPress scanner and confirm both scripts answer "already installed" and "No Update Required".

Where this fits

WordPress install or upgrade script reachable is check 1 of 10 that the website vulnerability scanner runs under wordpress plugins, themes and core, ordered the way they are worth fixing. That ordering is the point: Fixing this one while the check above it still fails buys less than it looks like.

What fixing this still leaves open

WordPress install or upgrade script reachable closes one route in. Immediately below it: Exposed wp-content/debug.log, where the WordPress debug log at /wp-content/debug.log is readable by anyone; Plugin version with known vulnerabilities, where at least one installed plugin is at a version with published vulnerabilities; Theme version with known vulnerabilities, where the identified theme is at a version with published vulnerabilities.

Found in the same scan

The website vulnerability scanner reports this alongside checks from other categories that are at least as serious, including Certificate chain and hostname validation, where the certificate presented for this hostname did not validate: The chain does not reach a trusted root, an intermediate is missing, the name does not match, or the certificate is self-signed or expired, and Exposed .env configuration file, where a .env configuration file is served from the web root. A single run of website vulnerability scanner answers all of them at once.

Prompt for an AI Hand this check to an assistant Sign in to copy it
The first few lines
You are a senior web engineer. I ran a security and SEO scanner against my site and it reported the finding below. Fix it properly rather than suppressing the symptom.

Finding: WordPress install or upgrade script reachable (critical severity)
Scanner check id: wordpress-install-script
17 more lines, including the evidence and the exact fix

The rest of this prompt names the pages and line numbers we found the problem on, the configuration to change, and the constraints a good answer has to respect. It is free, it just needs an account so the work is not scraped wholesale.

Sign in with Google

Signing in is free and takes one click. We store your email address and nothing else.

References

  1. WordPress: How to install WordPress
  2. WordPress: Hardening WordPress
  3. OWASP WSTG: Test Application Platform Configuration

Related guides