Pro feature
Features · AI Detection

WordPress database scanning, for the malware that doesn't live in files.

Roughly half of modern WordPress malware persists in the database rather than on disk. File scanners never see it. Guardian Gaze's database scanner reads wp_options,wp_posts, wp_postmeta and other tables directly, looking for encoded payloads, injected scripts, hidden admin users and persistence mechanisms that re-infect a site after a "clean".

Why this exists

Half of WordPress malware doesn't touch disk.

Database-resident malware is the category most file-only scanners blind themselves to. A payload stored in a wp_options row is loaded by WordPress on every request, executes, and leaves no file-system trace. The most common pattern we see: site is "cleaned" by deleting infected files, then re-infects itself a day later because the loader is still living in wp_options.

Guardian Gaze treats the database as a first-class scan target. We read it directly, decode every serialised blob, normalise the content, and run the same four detection layers (signature, heuristic, cross-reference, LLM) as we do on files.

Tables scanned

The four tables where most database malware hides.

⚙️

wp_options

The site-settings table. Common infection sites: injected scripts loaded by wp_head, malicious redirect URLs, stage-two loaders, backdoor configurations, fake plugin auto-loaders. We read both serialised and plain values.

📝

wp_posts

Posts, pages and any custom post type. Common infections: SEO spam pages, injected iframes, hidden links inside legitimate posts, redirect URLs in post_content, attacker-controlled custom post types.

🏷️

wp_postmeta

Per-post metadata, often serialised. Attackers hide payloads here knowing most scanners don't unwrap PHP-serialised data. We deserialise every row before analysis.

👤

wp_users & wp_usermeta

The user table. We surface accounts created after a known scan baseline, especially with Administrator role, and flag suspicious user-meta entries that look like persistence hooks.

What we catch

The specific patterns that show up on real compromised sites.

  • ROT13-, base64- and hex-encoded payloads in wp_options. Often loaded via a fake option name like wp_user_cache_data that masquerades as a normal WP transient.
  • Stage-two loaders. Database rows containing the URL or code of the next stage of a multi-stage compromise, invisible until triggered by a specific request.
  • Hidden iframes and script injections in wp_posts. Often inserted into the head or footer via a stored option, but sometimes directly into legitimate posts.
  • Hidden admin users. Accounts created post-compromise with Administrator role, often with a normal-sounding name to avoid suspicion in the user list.
  • SEO spam pages. Hundreds of low-quality auto-generated pages with hidden links to attacker domains, often with future-dated post_date to delay detection.
  • Fake transients. Persistent backdoors disguised as _transient_*rows so they look like legitimate WordPress cache entries.
  • Privilege-escalation hooks. Meta entries that grant admin capabilities to subscriber accounts under specific conditions.
  • Persistence mechanisms. Any database row that effectively reinstalls a backdoor, the most important category, because it explains why "cleaned" sites get re-infected.
Cross-referenced with files

Two-way correlation, not isolated findings.

A file scanner that flags "suspicious .php in uploads/" is useful. A file scanner plus database scanner that says "this file is loaded by wp_options row _active_backup_pluginvia auto-loader hook" is significantly more actionable. Guardian Gaze cross-references findings between layers so a single threat surfaces as one coherent issue rather than two unconnected ones.

Why this matters for cleanup

The most common cleanup failure pattern: site owner finds and deletes an infected file, but the wp_options row that loads it is still there. As soon as WP loads, the row's content runs, tries to load the deleted file, fails, and on many sites, also re-downloads or re-creates the file from a second source. Cleanup that only touches files almost always misses persistence. Cross-referenced cleanup gets both.

How it runs

Read-only access, no schema changes.

The database scanner connects directly to MySQL using your existing WordPress database credentials. It only reads, no writes, no schema changes, no triggers. Findings are sent to our API for analysis and stored in Guardian Gaze's own dashboard, not in your database.

Large tables are paginated and processed in chunks so the scan never holds long-running locks. On a typical site, the database scan adds 30 to 60 seconds to a deep scan. On a heavily-loaded WooCommerce site with millions of orders, we run the database scanner in the lowest-traffic hour by default.

Tier availability

Pro and above.

CapabilityFreeProAgency
wp_options scan
wp_posts & wp_postmeta scan
wp_users / hidden admin detection
Serialised payload deserialisation
Cross-reference with file findings
LLM analysis of suspicious rows
Custom-table scanning (custom post types)
Scheduled database scansHourlyHourly

Find what file scanners can't see.

Upgrade to Pro to add database scanning to your existing Guardian Gaze install. No schema changes, no downtime, results in under 10 minutes.