If one WordPress site in your hosting account was infected, treat every site in that account as compromised until proven otherwise. This infection is built to reinstall itself from multiple hiding places at once β including your browser β so a partial cleanup doesn't hold.
For site owners, admins & agenciesDo this on every site on the hosting account
β οΈ Cross-site contamination is the point of this guide.
On shared hosting, this malware actively scans for sibling WordPress installs under the same account and copies itself into every one it finds. Cleaning your main site while an old side project three folders over stays infected just gives it a way back in. Repeat every step below on each WordPress install you control on that hosting account, not just the one that showed symptoms.
1. Review admin users, then rotate every password
A large share of these infections start with stolen, reused, or leaked credentials β not a code exploit. Passwords harvested in unrelated breaches get tried automatically, in bulk, against thousands of WordPress logins until one matches. If any admin on this site reuses a password that's ever appeared in a public breach, this is likely how the door was opened.
Go to Users β All Users and filter by role. Look specifically at everyone with Administrator β that's the role attackers create for themselves.
βFor each admin, ask: do I know this person, and do they still need full admin access? Remove or demote anyone you can't account for, anyone who left the team, and anyone who only ever needed to publish posts.
βReset the password for every admin account that remains β not just the one you suspect was compromised. Open each user's profile, scroll to Account Management, and click Generate Password rather than typing your own; use a password manager to store a unique, 20+ character password per site.
βDo the same for Editor and Author accounts if the site accepts public registration or has ever had a support/contractor account added.
Illustrative mockup of the Users screen β not a screenshot of your actual site.
This infection also hides admin accounts from the Users screen. Researchers have observed rogue accounts (patterns like admin_a1b2, adm_9f3e) that are filtered out of the visible user list and recreated automatically by a scheduled task if deleted through the UI. If your visible admin count doesn't match what your host or a database tool (phpMyAdmin, WP-CLI's wp user list) reports for the wp_users table, there's likely a hidden account β that discrepancy is worth escalating to your host or a malware-removal specialist rather than working around it yourself.
2. Rotate your security keys (salts)
The eight security keys in wp-config.php are what WordPress uses to sign login cookies. Changing them invalidates every active session on the site instantly β your own, your team's, and any attacker's β even a session built from a cookie stolen days ago that hasn't expired yet.
Open WordPress.org's official secret-key generator and copy the eight lines it returns.
Open wp-config.php through your host's file manager or SFTP.
Find the block of eight
define('...KEY'...)/define('...SALT'...)lines and replace the whole block with the new one you generated.Save the file. Everyone β including you β will be logged out of wp-admin immediately. That's expected; log back in with your newly reset password.
// wp-config.php
define('AUTH_KEY', 'NEW-9k2j...');
define('SECURE_AUTH_KEY', 'NEW-p03m...');
β¦6 more, all freshly generatedβ¦
β No file access? Several web hosting providers expose a one-click "regenerate keys" or "change security keys" option in their own dashboard β check there first if sFTP isn't available to you.
β
If you have SSH access and WP-CLI is available you can easily run this command:
βwp config shuffle-salts
3. Audit Application Passwords
Application Passwords are a separate credential system WordPress uses for the REST API and third-party integrations β a mobile app, a form plugin, a publishing tool. They live outside your normal login password, don't rotate when you reset it, and are easy to overlook during cleanup.
Go to Users β Profile (your own account) and open every other admin's profile in turn. Scroll to Application Passwords.
βReview the list: name, date created, last used, last IP. Revoke anything you don't recognize, anything unused for months, and especially anything with a random-looking name.
βFor integrations you do recognize and still use, revoke the existing entry anyway and generate a fresh one β the old value can't be viewed again, so you'll need to paste the new password into that app or plugin's settings.
Illustrative mockup of the Application Passwords panel.
Check this after you've dealt with hidden admin accounts (step 1). An application password tied to a rogue account you haven't found yet won't show up here until that account itself is exposed.
4. Put a CAPTCHA on your login form
Credential-stuffing tools work by trying thousands of leaked username/password pairs against your login form automatically. A CAPTCHA breaks that automation β it doesn't need to stop a determined human, it just needs to stop a script.
Some popular plugins are:
Simple CAPTCHA β Cloudflare Turnstile Usually invisible to real visitors; good default choice
βreCAPTCHA by BestWebSoft - Google reCAPTCHA v2/v3 on the login form
βhCaptcha for WP - Privacy-focused alternative to reCAPTCHA
βAll In One Captcha - Lets you switch between Turnstile, reCAPTCHA & hCaptcha
β
βPick one provider and get free site/secret keys: Cloudflare Turnstile, Google reCAPTCHA, or hCaptcha.
Install the matching plugin from the list above and paste the keys into its settings.
Enable it specifically on the login form β not just comments or registration, which is where most CAPTCHA plugins default to protecting first.
5. Turn on two-factor authentication
A CAPTCHA stops bots; 2FA stops humans who already have a valid password. It's a second, independent layer: even if a password leaks again in some future breach β or an admin reuses one out of habit β login still requires a code from a device the attacker doesn't have. Rotating passwords fixes today's breach; 2FA limits the damage of the next one.
Two-Factor - Maintained by WordPress core contributors; TOTP, email codes, backup codes
βWP 2FA - Policy-based rollout β can require 2FA for all admins
βminiOrange 2FA - OTP via SMS, email, or authenticator app
Install one plugin and require it for every Administrator and Editor account at minimum.
Have each admin pair an authenticator app (Google Authenticator, Authy, 1Password) rather than relying on email codes alone, and save the printed backup codes somewhere offline.
6. Clean the reinfection out of your browser
This is the step that gets skipped, and it's the one that causes sites to reinfect right after they've been declared clean. The malware registers a Service Worker β a small background script your browser keeps running for the site's domain, independent of cookies or cache. It can silently re-upload the malicious plugin using your still-open admin session the next time you visit wp-admin, even on a server that's otherwise spotless. Every admin, on every browser and device they've used to log into this site, needs to do this.
Illustrative mockup of the browser DevTools Service Workers panel.
Chrome / Edge (Chromium)
Chrome / Edge (Chromium)
Visit the site, then open DevTools (
F12or right-click β Inspect).Go to the Application tab β Service Workers in the left sidebar.
Click Unregister next to any entry for the site's domain.
Still in Application, open Storage β Clear site data to remove cached files, IndexedDB and local storage the worker may have used to reinstall itself.
Firefox
Firefox
Go to
about:debugging#/runtime/this-firefoxand find the site under Service Workers.Click Unregister.
Then go to Settings β Privacy & Security β Cookies and Site Data β Manage Data, search for the domain, and remove it.
Safari
Safari
Enable the Develop menu if it isn't visible: Safari β Settings β Advanced β Show features for web developers.
Open Develop β [your Mac name] β yoursite.com and use the Storage panel to unregister its service worker, or simply choose Develop β Empty Caches.
Then go to Safari β Settings β Privacy β Manage Website Data, search for the domain, and click Remove.
β οΈ Repeat this on every device an admin has logged in from β phone, laptop, a second browser profile. A single missed browser is enough to trigger a reinstall.
7. Apply the principle of least privilege
Give every account, integration and credential the minimum access it needs to do its job β nothing more. It doesn't stop the first compromise, but it caps the damage: a stolen Author password can't create rogue admins, and a leaked Application Password scoped to one plugin can't touch the rest of the site.
Who | Default role | Not |
Writers / marketing | Author or Contributor | Administrator |
Agency / contractor, project-only | Editor, time-boxed | A permanent admin account |
A plugin or third-party app | Its own low-privilege user + scoped Application Password | Your personal admin's credentials |
True site administrators | The smallest number that can still run the site | Everyone on the team, by default |
Keep hosting-panel and SFTP credentials separate from WordPress admin logins, and never reuse a password across sites β even ones you own. One leaked site shouldn't be a key to the rest of your hosting account.
8. Stay clean going forward
Keep WordPress core, themes and plugins updated β enable automatic updates for anything you trust to update safely.
βDelete unused plugins and themes entirely; don't leave them deactivated on disk.
βAdd
define('DISALLOW_FILE_EDIT', true);towp-config.phpto block plugin/theme editing from wp-admin.
βImplement a RASP solution such as ThreatShield to filter malicious requests at their run time.
βTake regular offsite backups and actually test that you can restore one.
βRun ongoing malware and file-integrity monitoring rather than a one-time scan β this family is built to come back, and dedicated protection like Monarx's Agent and ThreatShield is designed to catch reinfection attempts at the file and runtime level.
βConfirm you've repeated steps 1β6 on every WordPress site in the hosting account β not only the one that first showed symptoms.
βIf anything here turns up more than you can confidently clean yourself, a professional cleanup is cheaper than a repeat infection.
Based on Monarx's research into the self-healing WordPress infection β read the full technical report. Screens shown in this guide are illustrative mockups, not screenshots of any specific site.



