I clean my site and the infection is back the next day
You delete the flagged files, everything looks normal for a few hours, then the exact same problem is back: a reload point is still in place somewhere, and it is rarely where the scanner looks.
Why a partial clean-up guarantees a repeat
When an infection returns identical after a clean-up, it is rarely a new attack. It is the same compromise reinstalling itself from a component the clean-up never touched. A compromised site usually holds two kinds of files: the ones producing the visible effect — a redirect, an injected page, an unexpected script on the checkout — and the ones that put them back. The first kind is noisy and a scanner finds it. The second is quiet, and usually sits somewhere the dashboard never displays.
While the reload mechanism is still in place, deleting the flagged files is sweeping in front of a door left open. The typical delay — a few hours, or overnight — is simply how often that mechanism fires. That is a useful clue in itself: a return at a fixed interval points to a scheduled task far more than to a repeated manual attack.
The practical rule follows: until I have found how the code comes back, I treat the site as still compromised, however clean it looks.
Signs that a reload point is still there
- The same files reappear, under the same or a very similar name, hours after being deleted.
- The scanner reports the site as clean, but the odd behaviour returns: a redirect, an unknown page, a script added to your pages.
- The infection comes back even though you have already changed every password.
- An administrator account you deleted reappears.
- The return happens at a regular interval rather than at random.
- Restoring a backup fixes things for a few days, then it comes back unchanged.
Why a scanner reading the plugin list misses it
WordPress has an auto-loading plugin folder, wp-content/mu-plugins/, known as "must-use". Code placed there runs on every page load, with no activation, and never appears in the plugin list in the dashboard. That is exactly what makes it a good hiding place. Sucuri documented attackers using this folder in March 2025, with three files observed: redirect.php, sending visitors to a malicious external page disguised as a browser update; index.php, a webshell granting remote access to the server; and custom-js-loader.php, replacing site content with unwanted links and tampering with images.
A tool comparing the admin list against a reference list will see none of it, because that folder's contents are never listed there. Themes have the same blind spot. A campaign analysed by Sucuri in May 2025 injected its code into the header.php file of every installed theme, including inactive ones, to serve visitors a fake anti-robot verification page. Cleaning the active theme then leaves as many intact copies as there are themes on the server: activating one is enough to bring it all back.
The detection advice is short: watch for unusual behaviour such as redirects and file changes, check for abnormal permissions, run file integrity monitoring, review administrator accounts, keep everything updated and enable two-factor authentication.
Persistence points, in the order I check them
-
Auto-loading plugins
I list the contents of wp-content/mu-plugins/ before anything else. On many healthy installs that folder does not even exist. If it exists and holds files nobody asked for, that is the reload point to deal with first, because it runs on every page load without ever showing up in the admin.
-
Inactive themes
I read the header file of every theme on the server, not just the active one. An unused theme is still a readable, writable file, and it keeps the injection intact after the live theme has been cleaned. A theme you do not use and do not plan to use should be deleted, not deactivated.
-
Scheduled tasks
I list the scheduler's events. In the phishing campaign analysed by Patchstack in April 2025, the malicious plugin scheduled a randomly named WP-Cron task running every minute, which reinstalled the payload. A task whose name you do not recognise, running at an abnormally high frequency, should be treated as a scheduled reinfection.
-
The active theme's functions file
In the ShapedPlugin supply chain compromise published in June 2026, loader code was injected into the active theme's functions.php and read a base64-encoded payload. This is a perfectly legitimate location, edited by plenty of plugins: it has to be read line by line, not scanned.
-
Administrator accounts
I compare the list of privileged accounts against what you actually expect. Several campaigns create administrator accounts, sometimes hidden from the user list shown in the dashboard. One forgotten account reopens full access, however carefully the files were cleaned.
-
API keys and tokens
Application passwords, API keys, OAuth tokens for connected services, two-factor secrets: if they could have been read, regenerating them is the only step that cuts access. An attacker still holding a valid token has no need for the backdoor you just removed.
ls -la wp-content/mu-plugins/
wp cron event list
wp user list --role=administrator --fields=ID,user_login,user_email,user_registered
wp theme list
find wp-content/themes -name "header.php"
find . -type f -name "*.php" -mtime -14
Related reading
-
Cleaning an infected site
The full procedure, in order, once the site is already compromised.
-
Staying protected after a clean-up
What is left to do once the files are gone, so the door does not reopen.
-
An unknown file on the server
How to qualify a file you did not upload before deleting it.
-
Checking whether my site is compromised
The checks to run when you have doubts but nothing is confirmed yet.
Describe your need in one minute
A few targeted questions so I can reply with an estimate rather than another questionnaire.