# 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.

- Source canonique : [https://allaux.fr/en/securite/infection-revient-apres-chaque-nettoyage](https://allaux.fr/en/securite/infection-revient-apres-chaque-nettoyage)
- Langue : EN
- Dernière mise à jour : 2026-09-30

## Direct answer

> List the contents of wp-content/mu-plugins/ first: that folder loads on every page render without appearing in the plugin list, and it is the most common reload point. Then review the scheduled tasks and the inactive themes. Until the original vulnerable component is identified and updated or removed, the next cleanup is already scheduled.

## 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

1. **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.
2. **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.
3. **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.
4. **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.
5. **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.
6. **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.

## Basic checks (shell and WP-CLI)

```
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
```

## The rule that prevents a third clean-up

> I do not put a site back online until the entry point is identified, not just the files that were dropped. Knowing what was deleted says nothing about how the attacker got in; while that answer is missing, the same route stays open and the next clean-up is already booked. My order never changes: vulnerable component identified then updated or removed, persistence points emptied, privileged accounts reviewed, secrets regenerated, and only then back online.

## Related reading

- **Cleaning an infected site** — The full procedure, in order, once the site is already compromised. ([/securite/nettoyer-un-site-infecte](/securite/nettoyer-un-site-infecte))
- **Staying protected after a clean-up** — What is left to do once the files are gone, so the door does not reopen. ([/securite/se-proteger-apres-un-nettoyage](/securite/se-proteger-apres-un-nettoyage))
- **An unknown file on the server** — How to qualify a file you did not upload before deleting it. ([/securite/fichier-inconnu-sur-le-serveur](/securite/fichier-inconnu-sur-le-serveur))
- **Checking whether my site is compromised** — The checks to run when you have doubts but nothing is confirmed yet. ([/securite/verifier-si-mon-site-est-compromis](/securite/verifier-si-mon-site-est-compromis))

## FAQ

### Why does the infection always come back after a few hours?

Because a reload mechanism is still running at a fixed interval. A randomly named scheduled task running every minute was documented in a campaign analysed by Patchstack; while it stays in place, deleting files only holds until its next run.

### My scanner says the site is clean, can I trust it?

Not on its own. A tool relying on the plugin list shown in the dashboard cannot see the contents of wp-content/mu-plugins/, which loads without activation and never appears there. I check that folder by hand, every time.

### Do I need to clean themes I do not use?

Yes, and deleting them is better. A campaign documented by Sucuri injected its code into the header.php file of every installed theme, active or not. An inactive theme is still a file on the server, so an intact copy of the injection.

### Is restoring a backup enough to fix it?

Rarely. A backup taken after the compromise already contains the reload point. One taken before it also restores the vulnerable version the attacker came through. A restore never replaces identifying the entry point.

### Should I rotate API keys even after removing every file?

Yes, as soon as a webshell or loader code could have run on the server. A token or key that is still valid grants access that no longer depends on any file being present on the site.

### When can I call it finished?

When the component the attacker came through is identified and fixed, the persistence points are empty, the list of privileged accounts matches what you expect, and the secrets have been regenerated. Before that, the site is not clean, only quiet.
