> ## Documentation Index
> Fetch the complete documentation index at: https://blog.onetsolutions.net/llms.txt
> Use this file to discover all available pages before exploring further.

# Hardening WordPress After wp2shell: Seven Measures That Actually Matter

> Two critical WordPress incidents in a fortnight, from opposite directions. A practical checklist: auto-updates, plugin hygiene, least privilege, and compromise checks.

<img src="https://mintcdn.com/onetsolutions-blog/2_5f6cjTs9e9BMUz/images/2026/08/wordpress-harden-en.webp?fit=max&auto=format&n=2_5f6cjTs9e9BMUz&q=85&s=85ce3c3039a6e526442690ad6f3fd1e9" alt="Hardening WordPress after wp2shell: core auto-updates, fewer plugins, no PHP execution in uploads" width="1200" height="628" data-path="images/2026/08/wordpress-harden-en.webp" />

*Published on August 8, 2026*

July 2026 delivered two WordPress incidents from opposite directions. [wp2shell](/en/wp2shell-cve-2026-63030) was a flaw in core itself — unauthenticated remote code execution, exploited within hours of disclosure. The [ARVE backdoor](/en/arve-backdoor-cve-2026-18072) was not a flaw at all, but a deliberate compromise of a plugin's distribution channel.

They defeat different defences. Plugin discipline would not have saved you from wp2shell. Prompt updating is what *delivered* the ARVE backdoor to anyone who received it. A checklist that only handles one shape of incident is not a checklist.

Here is what holds up against both, ordered by what it actually buys you.

## 1. Automatic updates on core, on purpose

Minor core releases carry the security fixes, and they are designed to be safe to apply blind. WordPress.org pushed forced updates for wp2shell — but only to sites where auto-updates were enabled and core files were writable.

```php theme={null}
// wp-config.php — minor releases only, the default and the right choice
define( 'WP_AUTO_UPDATE_CORE', 'minor' );
```

Verify what is actually in effect, rather than what you believe you configured:

```bash theme={null}
wp config get WP_AUTO_UPDATE_CORE
wp core version
```

<Warning>
  Sites deployed from Git with read-only core files silently opt out of this. If your deployment pipeline owns `wp-includes`, then your pipeline owns patching — and it needs to run on security releases, not on your sprint cadence.
</Warning>

## 2. Delay plugin updates, do not disable them

This is the one counter-intuitive item, and the ARVE incident is the argument for it.

Plugin backdoors are caught fast — this one in under two hours — but they are caught *after* publication. Applying every plugin update the minute it lands puts you first in line for a compromised release. Never applying them leaves you exposed to ordinary vulnerabilities, which are far more common.

The middle ground: automatic updates for plugins, deliberately lagging by a few days, with security releases exempt from the delay. Whatever tool you use to manage sites at scale, this is the setting to look for.

If you manage a handful of sites by hand, the same logic applies with less machinery: check for updates weekly, apply security ones immediately and the rest at your next pass.

## 3. Fewer plugins

Every plugin is a standing grant of code execution to a third party, renewed on every update. The strongest control is a shorter list.

```bash theme={null}
# Everything installed, active or not — deactivated plugins still sit on disk
wp plugin list --fields=name,status,version,update

# Remove what is inactive
wp plugin list --status=inactive --field=name | xargs -r -n1 wp plugin delete
```

Prefer plugins with several maintainers over single-maintainer ones. A plugin maintained by one person is one account away from what happened to ARVE.

## 4. Least privilege on accounts

The wp2shell chain ends by creating an administrator. Plenty of attacks end by *using* one that was lying around.

Most people who log into a WordPress site do not need to install plugins. Editor is enough to publish. Administrator should be a role held by one or two people, not the default for everyone with a login.

```bash theme={null}
# Who holds administrator rights, and since when
wp user list --role=administrator --fields=ID,user_login,user_email,user_registered

# Downgrade someone who only needs to publish
wp user set-role 12 editor
```

Turn on two-factor authentication for the accounts that remain. On the [OnetSolutions console](https://help.onetsolutions.net/console/security) it protects the hosting account itself, which is the layer underneath the site.

## 5. Cut off code execution in uploads

A web shell has to land somewhere, and `wp-content/uploads` is where it usually lands. That directory holds images and PDFs. It has no business executing PHP.

For nginx:

```nginx theme={null}
# In the site's server block
location ~* /wp-content/uploads/.*\.php$ {
    deny all;
}
```

For Apache, an `.htaccess` at the root of `wp-content/uploads`:

```apache theme={null}
<FilesMatch "\.(php|php\d|phtml|phar)$">
    Require all denied
</FilesMatch>
```

This is a cheap, near-zero-risk control that turns a large class of successful exploits into a file sitting harmlessly on disk. If your hosting lets you pick the [PHP version and handler](https://help.onetsolutions.net/web-hosting/php-version), check this rule survives the configuration.

## 6. Disable file editing from the dashboard

The dashboard's built-in plugin and theme editor lets anyone with administrator rights write PHP straight to disk. It is a convenience worth almost nothing and an escalation path worth a great deal.

```php theme={null}
// wp-config.php
define( 'DISALLOW_FILE_EDIT', true );
```

If you want to go further, `DISALLOW_FILE_MODS` also blocks installing and updating plugins and themes from the dashboard — appropriate for sites deployed from a repository, and disruptive for sites managed by hand. Note that it disables automatic plugin updates too, so only use it where the pipeline handles updates.

## 7. Backups you have restored at least once

Every incident response above ends the same way: restore from a backup predating the compromise. That step only works if the backup exists, reaches far enough back, and actually restores.

Three properties matter, and only the first is usually checked:

* **The backup runs.** Easy to verify, and where most people stop.
* **Retention outlives detection.** A compromise found in September needs an August backup. Seven days of retention is not a security backup, it is an undo button.
* **The restore has been tested.** Restore to a staging site once. It is the only way to learn that the database dump was truncated, before you need it.

Both [shared hosting backups](https://help.onetsolutions.net/web-hosting/backup) and [VPS snapshots](https://help.onetsolutions.net/vps/snapshot) are available from the console. Take a manual snapshot before every core update — it costs a minute and it is the rollback point you will want.

## A five-minute check, right now

If you do nothing else after reading this, run these four:

```bash theme={null}
# 1. Is core on a patched version? 6.9.5, 7.0.2 or later
wp core version

# 2. Any administrator account you cannot name?
wp user list --role=administrator --fields=user_login,user_email,user_registered

# 3. Any PHP written under wp-content in the last 30 days?
find wp-content -name "*.php" -mtime -30 -printf "%TY-%Tm-%Td %p\n" | sort -r | head -20

# 4. Is the ARVE plugin present?
wp plugin get advanced-responsive-video-embedder --field=version 2>/dev/null || echo "absent"
```

Four commands, and they cover the two incidents of the past month plus the most common signs of a site that was compromised earlier and never noticed.

<Note>
  None of this makes a site unbreakable. It shortens the list of things that break it, and it makes the ones that get through easier to spot and cheaper to recover from. That is what hardening is.
</Note>

Questions about a site hosted with us? [Our team is available](https://help.onetsolutions.net/console/support) from your client area.
