WordPress Malware Removal: A Free Step-by-Step Fix (2026)

Free file checks on our WordPress 7.1.2 test site after we planted seven harmless test markers, October 2026.
Short answer: You can remove most WordPress malware yourself, for free. Back up the hacked site, lock it down, then replace core files, plugins and themes with clean copies and check the places scanners skip: admin users, PHP files in uploads, must-use plugins, cron jobs and wp-config.php. On a test site where we planted seven harmless “infections”, free wp-cli commands plus find and grep found all seven. The free NinjaScanner plugin found two, and Wordfence’s free scanner would not run without a license sign-up. If you have no SSH access or the hack keeps coming back, paid cleanup starts at $229 a year with Sucuri, as of October 2026.
This guide covers the signs of malware, what each free tool caught on our test site, an 11-step cleanup, what paid services cost, and how to stop it happening again. If your problem is spam links or Japanese spam pages in Google, start with our guide to removing spam links after a WordPress hack, which goes deeper on database spam and search cleanup.
Quick facts
| Item | Details |
|---|---|
| What malware does on WordPress | Adds backdoors, hidden admin users, redirects, spam and scheduled tasks that reinstall the infection |
| Free tools that found all 7 planted items | wp core verify-checksums, wp user list, wp plugin list --status=must-use, wp cron event list, wp config list, wp db search, plus find and grep |
| NinjaScanner 3.3.1 (free) | Found 2 of 7 (the changed core file and the must-use plugin), with 4 false alarms; scanned 4,500 files in about 20 seconds |
| Wordfence 9.0.2 (free) | Will not start a scan until you register an email address for a free license, so it is not in our results |
| Time to clean the test site | The cleanup commands ran in under a minute once every item had been found |
| Paid cleanup, as of October 2026 | Sucuri from $229/year, MalCare Repair $299/year list price, Wordfence Care $590/year, Wordfence Response $1,250/year |
| Google review after cleanup | A few days to a few weeks, according to Google |
| Main way sites get infected | Vulnerable plugins: Patchstack says 91% of the 11,334 new WordPress vulnerabilities found in 2025 were in plugins |
Signs your WordPress site has malware
Some infections are loud. Many hide from the site owner on purpose. Look for:
- Redirects to spam, scam or “you won a prize” pages, sometimes only for visitors on phones or arriving from Google.
- Browser or Google warnings such as “Dangerous site” or “This site may be hacked” in search results.
- A notice from your host that your account was suspended or that malware was found.
- Admin users you did not create, often with names that look official, like
wp_sys_maintorsupport. - New or changed files you did not add, especially PHP files in
wp-content/uploads. - Spam in Google for your domain, such as pill, casino or Japanese pages. A
site:yourdomain.comsearch shows them. - A slow site or high server load with no traffic spike, or your server sending spam email.
- Search Console’s Security Issues report listing malware, hacked content or harmful downloads.
If you see any of these, assume the site is compromised until you have checked every place in the steps below.
Our test: seven harmless “infections” on a sandbox site
To see what free tools catch, we set up a fresh WordPress 7.1.2 install on our own computer, a small fake yoga studio site with six posts, two pages and an editor account, and planted seven test items. None of them was real malware: every file only printed a text string or a comment, every link pointed to a made-up .test domain, and every item carried a “WPS TEST MARKER” label. Never download real malware samples to test a scanner.
| # | Planted item | Where it lives | What it imitates |
|---|---|---|---|
| 1 | Two links in a hidden display:none block at the end of a post |
Database (post and its revision) | Spam link injection |
| 2 | An extra administrator, wp_sys_maint |
Database (users table) | Backdoor admin account |
| 3 | thumb-cache.php, which only prints a string through base64_decode |
wp-content/uploads/2026/10/ |
Dropped backdoor file |
| 4 | One comment line added to the root index.php |
WordPress core | Infected core file |
| 5 | wp-cache-helper.php, which adds an HTML comment to the footer |
wp-content/mu-plugins/ |
Hidden must-use plugin |
| 6 | An hourly event called wp_cache_cleanup_hook |
WordPress cron (database) | Reinfection task |
| 7 | An unknown constant and comment line | wp-config.php |
Changed config file |
We gave them boring names on purpose. Real malware rarely calls itself “malware”. It hides behind names like “cache”, “helper” or “maintenance”.
Which free tools found what
| Planted item | wp-cli and shell | NinjaScanner 3.3.1 (free) | Wordfence 9.0.2 (free) |
|---|---|---|---|
| 1. Hidden links in a post | Found (wp db search, post and revision) |
Not checked on a first scan | Could not scan |
| 2. Extra admin user | Found (wp user list) |
Missed | Could not scan |
| 3. PHP file in uploads | Found (find and grep) |
Missed | Could not scan |
4. Changed index.php |
Found (wp core verify-checksums) |
Found, with a side-by-side diff | Could not scan |
| 5. Must-use plugin | Found (wp plugin list --status=must-use) |
Found | Could not scan |
| 6. Cron event | Found (wp cron event list) |
Missed | Could not scan |
7. Constant in wp-config.php |
Found (wp config list) |
Missed | Could not scan |
| False alarms | 1 (a file from our Docker setup) | 4 (the same file, plus 3 default theme files) | n/a |
wp-cli: found all seven, but you have to read the output
wp-cli is the official command-line tool for WordPress, and most hosts that offer SSH include it. Two lessons stood out on our test site.
First, checksums only cover what WordPress.org ships. wp core verify-checksums caught the edited index.php straight away, but it says nothing about wp-config.php, uploads, must-use plugins or the database. That is why the other commands matter.

Users, must-use plugins, cron events and a database search on the test site, before cleanup, October 2026.
Second, several commands do not flag anything; they list everything and leave the judgement to you. wp cron event list printed 22 events, and the fake one sat among normal ones from WordPress, Wordfence and NinjaScanner. wp config list printed 16 constants, and only one was unusual. Knowing what a normal site looks like is half the job, so it helps to save this output while your site is healthy.
NinjaScanner (free): best for seeing what changed
NinjaScanner is a free scanner on WordPress.org with about 30,000 active installs as of October 2026. It runs on your own server with no account. On our test install it scanned 4,500 files in about 20 seconds, in the background, and split the report into eight pages: core, plugins, themes, files and folders, Google Safe Browsing, anti-malware, snapshots and other checks.

NinjaScanner 3.3.1’s first report on the test site, flagging the changed index.php, October 2026.
It flagged the edited index.php and offered “View changes”, “Restore file” and “Ignore file”. Its diff view was the most useful thing we saw in a free tool. It puts the original file next to yours and highlights the added line.

NinjaScanner’s “View changes” diff for the planted line in index.php, October 2026.
It also listed the must-use plugin as a file that does not match any known package. It missed the admin user, the cron event, the wp-config.php change and the uploads file. Its anti-malware signatures did not flag our uploads file, which makes sense: the file was harmless, and signature scanners look for known malicious code. That is the point of the find check. A PHP file in uploads is suspicious no matter what it contains.
Its database snapshot compares posts and pages with the previous scan, so a first scan cannot catch spam that is already there. Three of its four false alarms were Twenty Twenty-Five theme files that differed from the WordPress.org copy only in a “Tested up to” line. Scheduled scans and WP-CLI support are Premium only. On our sandbox the first scan attempt stalled because of a file permission problem in our own setup; once fixed, it ran normally.
Wordfence (free): needs a license first
Wordfence is the most installed security plugin on WordPress.org, with over 5 million active installs as of October 2026. The vendor says its free scanner checks for malware, backdoors, SEO spam, malicious redirects and code injections, with new malware signatures arriving 30 days later than in Premium.

Wordfence 9.0.2 on the test site, asking for a license before it will scan, October 2026.
On our test install, version 9.0.2 would not start a scan until we entered an email address and installed a free license from Wordfence. We did not create an account, so we cannot report what it would have found. If you are fine with registering, the free license costs nothing, and Wordfence publishes its own step-by-step cleaning guide.
WP Crontrol: see what cron actually runs
Cron events are a favorite reinfection trick: you delete the bad file, and an hourly task puts it back. The free WP Crontrol plugin, version 1.21.2 with over 300,000 active installs, shows every event in the dashboard and the function each one runs.

WP Crontrol 1.21.2 showing the planted hourly event on the test site, October 2026.
Our test event had no code behind it, so WP Crontrol marked its action as “None” and counted it under “Events with no action”. A real malicious event usually points to a function hidden in a rogue file, so look for hook and action names you do not recognize rather than for a warning.
How to remove malware from WordPress, step by step
These are the steps we used to clean the test site. The commands assume SSH with wp-cli. With only cPanel, you can do the same checks with File Manager and phpMyAdmin, just more slowly. Do the work from a computer you trust, since some infections start with a stolen password.
1. Back up the hacked site as it is
Copy the files and the database before you change anything, and store the copy outside your web folder.
wp db export backup-hacked.sql
tar czf site-files-hacked.tgz .
Label it as infected. If you have a backup from before the hack, restoring it is often the fastest fix, but you still need steps 3, 4 and 11, or the attacker can walk back in. Our WordPress backup plugin comparison shows real restores with free tools, and our UpdraftPlus review covers the most popular one in detail.
2. Put the site in maintenance mode
wp maintenance-mode activate shows visitors a short “briefly unavailable” message while you work. WordPress ignores that message after 10 minutes, so for a longer cleanup block public access at the server level or ask your host to do it.
3. Remove unknown admins and change every password
wp user list --role=administrator --fields=ID,user_login,user_email,user_registered
wp user delete 3 --reassign=1
Check the registration dates: an administrator created recently that nobody on your team added is a red flag. Reassign its content to a real user, then change the passwords for every admin, your hosting account, SFTP or SSH, and the database user. A new database password must also go into wp-config.php; our guide on how to edit wp-config.php shows where.
4. Reset the secret keys
wp config shuffle-salts replaces the keys in wp-config.php that sign login cookies. Everyone gets logged out, including an attacker with a stolen session.
5. Replace WordPress core files
wp core verify-checksums
wp core download --force --skip-content --version=7.1.2
Use your own version number. On our test site this overwrote the changed index.php in a few seconds, and the next checksum run passed. The download does not delete extra files, so remove anything reported as “should not exist” unless you know where it came from. On our sandbox, wp-config-docker.php belonged to the Docker image and was safe.
6. Reinstall plugins and themes from clean copies
Run wp plugin verify-checksums --all, then reinstall anything that fails with wp plugin install <slug> --force. This only covers WordPress.org plugins; download paid plugins and themes fresh from the vendor. Delete what you do not use, and never install nulled copies, meaning pirated paid plugins, which often ship with backdoors.
Then check the two places the normal Plugins list hides:
wp plugin list --status=must-use
wp plugin list --status=dropin
Must-use plugins in wp-content/mu-plugins run on every page, and you cannot turn them off from the dashboard. Drop-ins such as advanced-cache.php or db.php in wp-content are normal for some caching plugins, but you should recognize each one. In the dashboard, the Must-Use tab only appears on the Plugins screen when that folder has files in it.
7. Remove PHP files from uploads and look for hidden code
find wp-content/uploads -name "*.php"
grep -rln "base64_decode\|eval(\|gzinflate\|str_rot13" wp-content --include=*.php
find . -name "*.php" -mtime -7
Uploads should hold images and documents, not PHP. The grep will also match normal code inside some plugins, so focus on files you cannot explain. The last command lists PHP files changed in the past seven days, which is useful if you know roughly when the hack started.
8. Check wp-config.php and .htaccess by hand
Neither file is covered by checksums. Open wp-config.php next to wp-config-sample.php and look for include or require lines, long encoded strings, code above the opening comment, and constants you did not add. wp config list gives a quick list of what is defined. In .htaccess, remove rules you did not add, especially redirects that check where the visitor came from; our spam link cleanup guide shows an example.
9. Clean the database
wp db search "<script" --all-tables
wp db search "display:none" --all-tables
wp option get siteurl
wp option get home
Clean each infected post in the code editor, then delete old revisions that still hold the bad code. On our test site the hidden links were in the post and in revision 12; wp post list --post_type=revision --post_parent=6 listed it and wp post delete 12 --force removed it. Also check that siteurl and home still point to your own domain.
10. Delete unknown cron events
wp cron event list --fields=hook,next_run_relative,recurrence
wp cron event delete wp_cache_cleanup_hook
Delete only events you can identify as bad. If you are unsure, look the hook name up in the plugin that should own it, or check its action in WP Crontrol.
11. Check again, reopen and ask Google to review
Run every check a second time. On our test site the second run was clean apart from the known Docker file, and NinjaScanner’s second scan took about 10 seconds.

The same checks after cleanup on the test site, October 2026.
Then run wp maintenance-mode deactivate, update everything, and test the site on your phone and from a Google result. If Search Console shows a security issue, fix every listed problem, then click Request Review in the Security Issues report and describe what you did. Google says a review takes from a few days to a few weeks, and asks you not to resubmit before you get a decision.
Free vs paid malware removal
Doing it yourself costs nothing but time, and on a small site with SSH access it is a few hours of careful work, not a week. Paying makes sense when you cannot use SSH, the site makes money every hour it is down, the infection keeps coming back, or your host has suspended the account and wants proof of a cleanup.
Most security companies sell cleanup as a yearly plan, not a one-off fee. These are the public prices as of October 2026:
| Service | Price | What the vendor says you get |
|---|---|---|
| Sucuri Website Security Platform | Basic $229/year, Pro $339/year, Business $549/year | Unlimited manual malware cleanups on every plan; malware removal response targets of 30, 12 and 6 hours; a 30-day guarantee |
| MalCare Repair | $299/year list price ($179.40 with a 40% discount shown when we checked) | Malware cleanup, a post-cleanup report and an expert response within 24 hours |
| MalCare Fortify | $499/year list price ($299.40 with the same discount) | Unlimited manual security fixes, hourly scans and an expert response within 6 hours |
| Wordfence Care | $590/year per site | Wordfence’s team cleans the site during business hours (9am to 8pm ET, weekdays), plus security audits and Premium features |
| Wordfence Response | $1,250/year per site | A 1-hour response, 24 hours a day, every day, and the vendor says it resolves security issues within 24 hours |
A few things to check before you pay: whether the plan covers every site on the same server (Wordfence says sites that are not isolated from each other all need a license), whether staging copies cost extra, and what happens at renewal. MalCare’s cheapest paid plan, Protect, does not include cleanup. Also ask your host first. Some include cleanup in the plan: Kinsta, for example, says every plan has a hack-fix guarantee, as our Kinsta review explains.
How to keep malware from coming back
Most hacks come through known holes in plugins. Patchstack’s State of WordPress Security in 2026 report counted 11,334 new vulnerabilities in 2025, up 42% from 2024. It found 91% were in plugins, 9% in themes and only 6 in WordPress core, and 46% had no fix from the developer by the time they were made public.
- Update quickly. Turn on automatic updates for plugins you trust, and test bigger updates on a staging copy of your site first.
- Delete what you do not use. Inactive plugins and themes can still be attacked.
- Lock down logins. Use strong, unique passwords, two-factor login and as few admin accounts as possible.
- Turn off the file editor with
define( 'DISALLOW_FILE_EDIT', true );inwp-config.php, so a stolen admin login cannot edit PHP from the dashboard. - Block PHP in uploads. Your host or a security plugin can add the rule for you.
- Keep off-site backups that go back several weeks, since some infections sit quietly for a while. All-in-One WP Migration can also move a clean copy to a new server.
- Choose a host that helps. Managed WordPress hosting isolates sites, keeps server software current and often includes malware scanning.
Once a month, run the checks from this guide: core and plugin checksums, the admin list, must-use plugins, PHP files in uploads and the cron list. Saving the output from a healthy site makes the next comparison much faster.
FAQ
Can I remove malware from WordPress for free?
Yes. On our test site, free wp-cli commands plus find and grep found all seven planted items, and the cleanup commands ran in under a minute. You need SSH access or patience with File Manager and phpMyAdmin. Free plugins such as NinjaScanner help, but none found everything on our test site.
Is Wordfence free enough to remove malware?
It may be, but you have to register an email address for a free license first. Version 9.0.2 would not scan on our test site without one, so we could not test it. Its free malware signatures arrive 30 days after Premium’s, which costs $149 a year as of October 2026.
How do I find malware without SSH?
Use the dashboard and your host’s tools. Check Users for unknown administrators, look for a Must-Use tab on the Plugins screen, install WP Crontrol to see cron events, run a scanner such as NinjaScanner, and use File Manager to look for PHP files in wp-content/uploads and recent changes to wp-config.php and .htaccess.
Should I restore a backup or clean the site?
Restore if you have a backup from before the hack and can tell when the hack started. It is usually faster. Either way, update everything, remove unknown admins, change all passwords and reset the secret keys, or the attacker can get back in the same way.
How much does professional WordPress malware removal cost?
As of October 2026, Sucuri’s plans with unlimited cleanups cost $229 to $549 a year, MalCare Repair lists at $299 a year, Wordfence Care costs $590 a year and Wordfence Response $1,250 a year. All are yearly subscriptions per site rather than one-off fees.
Why does malware keep coming back after I remove it?
Something was missed: a backdoor file, a hidden admin, a must-use plugin, a cron event that reinstalls the code, or the original hole, usually an outdated plugin. Another infected site on the same hosting account can also reinfect yours. Check every place in this guide, update everything, and change all passwords again.