You can tell whether a WordPress site is infected in about five minutes without installing anything: check five places in order — robots.txt, your sitemap, the administrator list, the plugin list, and the newest files in wp-content. If two or more of those come back with something you did not put there, treat the site as compromised and work from that assumption. The order matters because it runs from cheapest to slowest, and a single odd result is usually a false alarm while a pattern is not.
I ran exactly this sequence on my own blog after it started serving Japanese spam, and the first check was enough to confirm it. Here is the whole thing, with what each result actually means.
The short version
- robots.txt — fetch it raw. Attackers add
DisalloworSitemaplines pointing at paths and domains you never created. - Sitemap — open
/wp-sitemap.xmland look for URLs that are not your posts. - Users — filter the list to Administrators. Note anything you did not create; delete nothing yet.
- Plugins — compare against what you remember installing. Unknown folders, missing authors, and deactivated-but-present plugins are the tells.
- Files — sort
wp-contentby modified date. Anything changed in the last 48 hours that you did not touch is a suspect.
Check 1: robots.txt takes ten seconds
Open https://yoursite.com/robots.txt in a browser with no cache, or fetch it from the command line. A normal WordPress install has almost nothing in it:
User-agent: *
Disallow: /wp-admin/
Allow: /wp-admin/admin-ajax.php
Sitemap: https://yoursite.com/wp-sitemap.xml
What you are looking for is anything extra. Injected lines usually look like this:
User-agent: *
Disallow: /go/
Sitemap: https://example-spam-domain.top/sitemap.xml
A Disallow on a path you never created is the attacker hiding a doorway directory from crawlers. A Sitemap line pointing off your domain is the attacker advertising theirs. Either one is a confirmed infection — nothing legitimate writes those lines into robots.txt.
Note that the file may be generated by a plugin such as Yoast or Rank Math, or it may be a physical file on disk. If it is static, check its timestamp in your file manager as well: a modification date you cannot explain is its own signal.
Check 2: the sitemap shows what got published behind your back
Open https://yoursite.com/wp-sitemap.xml, or /sitemap_index.xml if a plugin manages it. Then open the posts sitemap itself and scan for words you would never write — brand names, a language you do not publish in, or a redirect path like /go/.
Two different things show up here, and they mean different things:
- URLs that resolve to real posts — someone published content through your dashboard. Check the post author and the revision history before deleting anything.
- URLs that 404 or redirect — the entries were injected into the sitemap rather than created as posts. That points at a modified theme file or a plugin, not at a hijacked login.
If your sitemap is clean but robots.txt carried an injected Sitemap: line, the attacker is advertising their own sitemap instead of yours. That is still an infection, and it still needs the same cleanup.
Check 3: the administrator list
In the dashboard go to Users and filter by Administrator. Count them, then look at the email domain and the username pattern of anyone you do not recognise. Attacker accounts very often use a throwaway address and a name that would look like a normal subscriber if you only glanced at it.
Do not delete the account yet. Deleting a user while the malware is still live can trigger a re-creation routine on the next page load, and you lose the only evidence of how it got in. Note the username, change your own password, and enable two-factor authentication first. If a plugin on your site records last login, check whether the suspicious account has ever actually logged in: an administrator that has never logged in was probably created by a script, which means the entry point is still open.
Check 4: plugins and themes
Open Plugins → Installed Plugins and actually read the list rather than scanning for update badges. The tells are boring, which is exactly why they get missed:
- A plugin you did not install, often with a generic name like “WP Cache Manager Pro” or unusual capitalisation.
- A plugin that is deactivated but still present. A deactivated plugin is not executed, so malware packs usually pair it with a must-use plugin that re-activates it.
- An author field that is empty, or a version number that does not match the plugin’s real release history.
- A second theme next to your active one that you never installed.
Now open wp-content/mu-plugins through your host’s file manager. Must-use plugins have no dashboard entry at all, load on every request, and cannot be deactivated from the admin. If that folder holds files you did not add, you have found the loader.
Check 5: files that changed recently
This is the slowest check and the most conclusive. Open the file manager or connect over SFTP, go to wp-content, and sort by last modified, newest first. Then look at three things.
PHP files inside uploads/. There is no legitimate reason for an uploads folder to contain a .php file. One is enough to be certain: that is a backdoor.
Core files. Files in wp-includes/ and wp-admin/ should change only when you update WordPress. If their timestamps do not line up with your last update, compare them against a fresh copy of the same version and diff the two.
Your theme’s functions.php. Attackers like it because it loads on every request and scanners tend to ignore theme files unless they recognise the payload. Look for long base64 blobs, eval(), gzinflate(), or an unexplained block of code at the very top of the file.
What the results mean
| What you found | What it usually means | Next step |
|---|---|---|
| Injected lines in robots.txt | Confirmed infection, spam injection | Restore robots.txt, then find the loader in mu-plugins |
| Unknown URLs in the sitemap | Posts created through the dashboard, or an injected sitemap | Check post authors and revisions |
| An admin you did not create | Dashboard credentials are compromised | Change every password, enable 2FA, then remove the account |
| Unknown or deactivated plugin | Malware pack left behind after an earlier cleanup | Remove the folder entirely, not just deactivate it |
| PHP in uploads/ or a modified core file | Active backdoor | Full restore from a clean backup, then rotate keys and passwords |
| Only old timestamps, nothing unusual | Probably not infected | Re-run in 24 hours; the checks are cheap |
A five-minute checklist you can repeat
- Fetch
/robots.txtand read every line. - Open the sitemap and scan for foreign URLs.
- Count administrators against who should be there.
- Read the plugin list and check
mu-plugins. - Sort
wp-contentby modified date and look at the top ten entries.
Run it once a month, and again the moment something changes: a sudden drop in traffic, a manual action in Search Console, or a page ranking in search that you never wrote. The checks do not prevent an infection, but they shorten the gap between the infection and the cleanup — and that gap is the part that actually costs you traffic and trust.
Start with robots.txt today. It is ten seconds, and it is the single check most likely to tell you the truth on the first try. If you have already found something, the full order of operations I used is written up in my post on recovering a hacked WordPress site. If you are unsure whether a specific file is legitimate, send me the first twenty lines through the contact page and I will tell you what it does. More write-ups like this live under the WordPress category.

Leave a Reply