Scan-and-delete only
Flagged files were removed, but components were never rebuilt from trusted sources — so anything the scanner did not recognize stayed exactly where it was.
Case study · WordPress incident response
A production e-commerce site had been cleaned three times by three different parties, and the malicious behavior returned after every cleanup. The fourth engagement treated the recurrence itself as the finding — and ended the cycle by closing what the earlier cleanups had left behind. This anonymized account shows the investigation pattern while withholding client-identifying and attacker-useful details.
Published Last reviewed
Starting condition
By the time the engagement began, the pattern was well established: a scan or manual cleanup would remove the visible malicious files, the site would behave normally for a while, and then the same class of malicious behavior would reappear. Each round cost the owner cleanup fees, lost sales during the disruption, and — more damaging for an e-commerce business — growing doubt about whether the store could be trusted at all.
Recurrence after cleanup is itself diagnostic. It meant at least one of four things had survived every attempt: a persistence mechanism outside the locations being cleaned, an access path the attacker could reuse, a compromised neighboring component within the same hosting boundary, or a credential that rotation had missed. The engagement was therefore scoped as an incident investigation with the explicit goal of ending the cycle — not as a fourth cleanup.
Importantly, the earlier cleanups were not incompetent; they were incomplete in a specific, common way. Each had focused on the visible file layer — the layer scanners report — while the mechanisms that restored the infection lived elsewhere.
Why the cleanups failed
Several of the classic cleanup-failure patterns were present in this engagement’s history. They are worth naming because they repeat across almost every reinfection case:
Flagged files were removed, but components were never rebuilt from trusted sources — so anything the scanner did not recognize stayed exactly where it was.
Cleanup stopped at the filesystem. Persistence stored in WordPress records survives every file-level cleanup and theme reinstall untouched.
The WordPress admin password changed; hosting, database, FTP/SFTP, and session-level access did not all change with it — leaving the attacker a way back that made the next “cleanup” irrelevant.
None of the three rounds asked how access was first obtained. The door that admitted the attacker stayed open through all three.
Each round ended when the visible symptom disappeared — before caches expired, scheduled tasks ran, and normal traffic resumed, which is exactly when the infection reloaded.
The investigation
Document the observed behavior, the full cleanup history, every access route (WordPress, hosting panel, database, SFTP, deployment), the hosting boundary, and the business constraints on downtime.
Review each location capable of restoring malicious behavior — files, database records, the active theme, PHP and server configuration, scheduled tasks, and accounts — and give each an explicit trust decision rather than a scan pass.
Remove untrusted artifacts, rebuild affected components from known-good sources, reconcile legitimate customizations separately, and rotate every relevant credential and session from a clean device.
Address the most likely initial-access condition supported by the evidence, apply the agreed hardening, and recheck the environment past the points where earlier cleanups had declared victory.
If this is your site
The full checklist is in the reinfection guide; these are the layers that most commonly survive a cleanup:
Outcome
The engagement removed the identified persistence, restored affected components from trusted sources, reset every relevant access path, and addressed the most likely entry condition available within the evidence and scope. Verification then deliberately extended past the milestones where the previous cleanups had stopped — through cache expiry, scheduled execution, and a return to normal traffic — and the recheck confirmed the environment stayed clean.
Just as important for the owner: the result was documented. The report recorded which layers had held the infection, what was rotated and rebuilt, which entry condition was addressed, and what residual dependencies remained — so any future responder starts from evidence instead of repeating the same assumptions a fourth time.
Because public case studies should not provide a roadmap back into a former client environment, exact indicators, filenames, infrastructure, dates, and access paths are intentionally omitted.
Lessons