Skip to main content
mySites.guru
New features added last monthRelease RadarFile ManagerImpostor FilesUpdate QueueRogue AdminsMCP & APIJoomla VELCVE Index

Suspect WP Options

Suspect WP Options

The wp_options table has no size limit and nothing scans it, which makes it a comfortable place for a payload. How suspect rows are found without reading them.

What this check and mySites.guru tool looks at on your site

wp_options is WordPress’s general-purpose settings table. Anything can write to it, rows have no size limit, and nothing scans it. That combination makes it a comfortable place to keep a payload, because a file scanner cannot see into your database at all.

On every snapshot mySites.guru looks at that table and reports the rows that stand out. It asks four questions of each row, and none of them involves reading what is in it.

  • Is the name nothing but hexadecimal characters? WordPress and its plugins name their settings after what the setting does. A name that is a bare string of 10 to 12 hex digits, anchored at both ends, is a label generated by a program. This is the strong signal.
  • Is the name one a known malware family uses? The family this was built against keeps its payload under its own small set of option names, and hides some of them behind WordPress’s own transient prefixes. The wrapper is stripped exactly once before comparing.
  • Do the first eight bytes look like compressed, encoded data? A cheap extra check on the head of the value.
  • Do they look like an opening PHP tag? Kept because it costs nothing and catches other families, though it caught none of the rows on the site this was calibrated against.

No option values leave your server during the sweep

The check collects the name of the row, how many bytes it holds, whether WordPress loads it on every request, and the first eight bytes as a fingerprint. Eight bytes is enough to tell compressed data from plain text and far too little to be anything else. The contents of your settings stay on your site unless you ask to see one specific row.

The anchoring in that hex rule is doing real work. Formidable Forms writes frm_form_templates_ followed by 32 hex characters, and Elementor Pro writes elementor_pro_api_request_ followed by 15. A rule that matched a hex tail instead of the whole name would report every site running either of them as hacked.

Alongside the findings, the tool reports how many bytes of your options table WordPress loads on every single page view. That is a speed number rather than a security one, and it has no tier and no colour. It is counted against all four values WordPress accepts in the autoload column, because 6.6 added a new vocabulary and did not rewrite existing rows, so an upgraded site holds both generations forever.

Why size turned out to be no signal at all

The obvious rule for a table holding an 837,308 byte payload is a size threshold. Three real options tables were available to compare: one from a compromised site, the same site after it was cleaned, and a stock WordPress install.

SignalInfected siteSame site, cleanedStock WordPress
Option rows860774143
Total option bytes4,807,6241,393,04386,015
Largest single row837,308372,55330,181
Rows over 64KB1550
Option names matching ^[0-9a-f]{10,12}$3200

Size does not separate those three columns. The bare hexadecimal name separates them perfectly, and it is nearly free to test.

The case that settles it is rewrite_rules, which is part of WordPress itself, exists on every WordPress site there has ever been, holds the compiled permalink rules and grows past 64KB on any site with enough pages and custom post types. A tier that fires on that is measuring how big a site is. So a large row is context: listed with its byte count and a vendor label where the name is recognised, with no warning, no tier and no contribution to the number on your audit row. A site with nine large rows and nothing else gets a green tick.

There is a corollary worth stealing for your own tooling. Do not calibrate a size rule on “bigger than the malware we found”. The largest legitimate row measured so far is 1,891KB and the largest malicious one is 818KB, so that threshold clears the sick site and flags the healthy one.

A vendor name is a label, never a permission

Where a large row’s name is recognised, the tool prints a short vendor string beside it and nothing else. Attribution runs last, and only while a row is still judged clean, so a name that tripped any rule never reaches the vendor table at all. That ordering is what makes the list safe to be incomplete: an unrecognised large row renders in the same neutral list as a recognised one, just without a name beside it. A missing entry costs a missing word.

The label says who a row is named after, never who wrote it, because the name comes from the site being examined.

Every option row accounted for

Nothing in your settings table has a name that looks generated rather than chosen. No row holds compressed or encoded data. The large rows you do have are ones you can attribute to a plugin you installed on purpose.

How to fix it

  1. Treat this list as a place to look. It is the yellow, human-judged twin of Suspect Content rather than a red one.
  2. Start with the names, not the sizes. A row named after nothing is far more interesting than a large row named _transient_something_sensible.
  3. Recognise before you remove. Deleting the wrong settings row breaks a plugin, and there is no undo. If you do not know what a row is, search its name before touching it.
  4. Do not clean the database and stop there. If something is writing payload rows, it has a way in and something that keeps it running. Check your scheduled events and your must-use plugins and drop-ins in the same sitting.
  5. Ask. If a row looks wrong and you are not sure, that is exactly the kind of thing to send in.

What mySites.guru does about it

On every snapshot, twice a day, mySites.guru sweeps your options table and reports what stands out, without collecting a single option value. This check reports rather than accusing: it does not mark a site as hacked, because the cost of a false confirmation is telling a paying customer their site is infected when it is not.

A row the check actually accused can be read one value at a time, capped at 64KB and gated on that exact name, and then deleted. A large row it merely listed cannot be deleted from here, on purpose. The delete goes through WordPress’s own function so the options caches clear, and the result is then confirmed by reading the table again.

On a multisite network each site has its own options table, and mySites.guru reads the one belonging to the address you registered.

Suspect WP Options

mySites.guru checks every connected site for this automatically and flags it the moment it appears. These run twice a day on every connected site.

Further Reading

Frequently Asked Questions

Can WordPress malware really live in the database rather than in files?
Yes, and wp_options is the comfortable place for it. Anything can write to it, rows have no size limit, and nothing scans it. On the site this check was calibrated against, 88 rows held 3.2MB of the malware's own compressed source, the largest of them 837,308 bytes in a single row. A file scanner cannot see any of that, because none of it is a file.
Does mySites.guru read the contents of my settings?
Not during the sweep. The check collects the name of each row, how many bytes it holds, whether WordPress loads it on every request, and the first eight bytes as a fingerprint. Eight bytes is enough to tell compressed data from plain text and far too little to be anything else. One value can be fetched later, capped at 64KB, but only when you ask to see that specific row.
Is a large option row a problem?
No, and that was measured rather than assumed. A tier that flagged anything over 64KB produced dozens of rows across live sites and not one of them was a problem: directory size caches, page builder caches, backup histories, analytics logs. WordPress core's own rewrite_rules grows past 64KB on any site with enough pages. Size is shown as context with no colour and no contribution to the count on your audit row.
What makes an option name suspicious then?
A name that is nothing but hexadecimal characters. WordPress and its plugins name their settings after what the setting does, so a bare string of hex digits is a label generated by a program. On the three real options tables this was calibrated against it separated them perfectly: 32 such names on the infected table, none at all on either clean one.
EU icon: AI MODIFIEDWritten and edited by a human, with AI assistance. Our approach to AI

What our users say

Artful Web Print Design
Artful Web Print Designartful.com.au
★★★★★

Having all our managed sites in one place is an incredible a time saver not to mention receiving the heads up on updates and vulnerabilities, tracking php versions and software via tagging. Invaluable to our business.

Read more reviews
Kees van D.
Kees van D.Van Dongen Design
★★★★★

I manage 80+ websites for my clients. It's such a relief to manage all services from one platform. Wish I had discovered this a long time ago :) Great services, unmissable if you manage more websites, it is saving me so much time and gives much more secure feeling. Thanks Phil!

Read more reviews

Read all 282 reviews →

See where your own sites stand

This check, and every other one, run automatically on a free audit. No credit card required.

Get Your Free Site Audit