Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AI Malware Scanner

A read-only WordPress malware scanner your AI assistant can drive over the Model Context Protocol.

WordPress PHP License

Turns WordPress into an MCP server so an assistant like Claude can scan the site on request, read the files it flags, and explain what it found — instead of handing you a list of rule names to decode yourself.

It cannot delete, modify, quarantine or move anything. That is the point. A plugin that deletes files on command from a remote endpoint is itself a backdoor; the only thing separating it from the malware it hunts is who holds the token.


Why this exists

Signature scanners produce noise. On a real infection this plugin was tested against, the signature scan returned 76 high-severity hits and 23 were real — the rest were a sentiment-analysis library and a bundled SSH client sitting inside reputable SEO plugins.

The integrity checker found the same 23 with zero false positives, because it compares every core file against the official wordpress.org checksum manifest. A checksum mismatch is a fact. A pattern match is a guess.

Both are included. Judgement about which to trust is the part an AI assistant is actually good at.


The four scanners

File signatures — webshells, obfuscated payloads (eval on decoded strings, layered base64 + gzinflate, chr() assembly), request-driven code execution, command execution, PHP in the uploads directory, double extensions, unexpected PHP in the document root, must-use plugins, drop-ins, search-engine verification files.

Core & plugin integrity — every core file against api.wordpress.org checksums for your exact version, and every wordpress.org plugin against its published manifest. Reports modified, missing, and unexpected files. Catches injected backdoors that signature scanning misses entirely, because attackers usually add files rather than edit them.

Database & users — administrator accounts, passwordless temporary logins, roles granted admin capabilities, active sessions with IPs and user agents, orphaned cron events, options containing PHP, snippet-plugin code stored in the database, external scripts injected into content. Cleaning files without this leaves the attacker a way back in.

Crawler cloaking — fetches your own site as Googlebot, AdsBot, Mediapartners and bingbot, then diffs each response against a normal browser. Cloaking is invisible to the site owner by design.


MCP tools

Tool Purpose
sentinel_site_info Versions, plugins, mu-plugins, drop-ins, hardening constants
sentinel_scan_files Signature + heuristic scan (resumable)
sentinel_check_integrity Core + plugin checksums vs wordpress.org (resumable)
sentinel_scan_database Users, sessions, cron, options, snippets, content
sentinel_check_cloaking Googlebot / AdsBot / bingbot response diffing
sentinel_read_file Read a flagged file (root-confined, secrets redacted)
sentinel_recent_files Files modified since a date, newest first

scan_files and check_integrity are resumable: each pass takes a wall-clock budget, stops before the host kills it, and returns a cursor. The assistant keeps calling until complete is true, so a large site finishes instead of dying against max_execution_time.


Install

From a release

Download the latest zip from Releases, then WordPress → Plugins → Add New → Upload Plugin.

From source

git clone https://github.com/sameeullah/ai-malware-scanner.git
cd ai-malware-scanner

Copy or symlink into wp-content/plugins/. There is no build step — no Composer, no npm, no compiled assets. What you read is what runs.

Connect an MCP client

  1. Activate, then go to Tools → AI Malware Scanner
  2. Connection & token tab → Generate token (shown once; only a SHA-256 hash is stored)
  3. Add the MCP URL as a custom connector:
    https://example.com/wp-json/ai-malware-scanner/v1/mcp
    
  4. Set the authorization header to Bearer <your token>
  5. Ask: "Run a full security scan"

If your client can't send custom headers, append the token to the path instead — /mcp/<token>. Works everywhere, but the token lands in your access logs, so rotate it.

Verify reachability:

curl https://example.com/wp-json/ai-malware-scanner/v1/ping
# {"service":"ai-malware-scanner","version":"1.0.0","ready":true}

Security model

Read files inside the WordPress root yes
Verify checksums against wordpress.org yes
Read users, options, cron, posts yes
Fetch its own site as a crawler yes
Write, delete or move any file no
Modify or delete database rows no
Execute shell commands or arbitrary PHP no
Read outside the WordPress root no
Return DB passwords or auth salts no — redacted
  • 64-character bearer token, stored only as a SHA-256 hash, compared with hash_equals()
  • Endpoint closed until a token is explicitly generated; deactivation revokes it
  • Optional IP allowlist (IPv4 + IPv6 CIDR)
  • Rate limited per IP
  • Every authentication attempt logged, allowed or denied

Found a vulnerability? Please report it privately via GitHub Security Advisories rather than a public issue.


What leaves your server

Nothing, until you connect a client.

Once connected, scan results — file paths, contents you ask the assistant to read, usernames, email addresses, session IPs — go to whichever AI provider you chose, under their privacy policy.

The integrity checker calls api.wordpress.org for checksum manifests. That request carries your WordPress version and plugin slugs, nothing site-identifying.


Layout

ai-malware-scanner.php              Bootstrap, constants, class map
includes/
  class-sentinel-auth.php           Tokens, rate limiting, IP allowlist, access log
  class-sentinel-mcp-server.php     JSON-RPC 2.0 over Streamable HTTP
  class-sentinel-tools.php          Tool schemas and dispatch
  class-sentinel-report.php         Finding collection and severity
  class-sentinel-results.php        Persists findings for the admin dashboard
  class-sentinel-budget.php         Wall-clock budget for resumable passes
  class-sentinel-admin.php          Tabbed admin UI
  class-sentinel-plugin-info.php    Native "View details" modal
  scanners/
    class-sentinel-scanner-files.php
    class-sentinel-scanner-integrity.php
    class-sentinel-scanner-database.php
    class-sentinel-scanner-cloaking.php
uninstall.php                       Removes every option and transient
readme.txt                          WordPress.org directory metadata

An explicit class map is used instead of a filesystem-scanning autoloader — that construct is exactly what a security plugin should not ship.

Tool descriptions in class-sentinel-tools.php are load-bearing. They are the only instructions the model receives about when a tool applies and how to drive a resumable scan, and are written for that reader rather than as API docs.


Development

No dependencies to install. To check it before a PR:

# WordPress coding standards
composer global require wp-coding-standards/wpcs
phpcs --standard=WordPress .

# The same checks wordpress.org runs
# (install "Plugin Check" from the plugin directory, then)
wp plugin check ai-malware-scanner

Direct $wpdb calls in the database scanner carry phpcs:disable blocks with justification inline. They are deliberate: no Core API can search option_value or do post_content LIKE, and caching would be a defect — a scanner reporting stale state actively lies.


Known limitations

Stated plainly, because a security tool that oversells itself is worse than none.

  • Loopback fetches. The cloaking check requests your site from your own server. Many hosts block this. The tool reports the failure rather than a false all-clear — verify manually with curl -A "Googlebot/2.1 (+http://www.google.com/bot.html)".
  • Premium plugins are unverifiable, not verified. No published manifest means nothing to compare against.
  • Cloaking tests one URL at a time, the homepage by default.
  • Signature scanning produces false positives. Read what it flags; that's why sentinel_read_file exists.
  • Multisite is lightly tested.
  • It finds; it does not fix. By design.

Roadmap

  • Skip signature analysis on plugins that verify clean against wordpress.org (would have removed nearly every false positive in testing)
  • Scheduled scans with email alerts on critical findings
  • Multi-URL cloaking checks
  • Exportable incident report

Contributing

Issues and pull requests welcome. For code changes, please run PHPCS against the WordPress standard and Plugin Check before opening a PR, and keep the read-only guarantee intact — any patch introducing a write path to site files or rows will be declined regardless of how useful it is.


License

GPL-2.0-or-later. See LICENSE.

Author

Samee Ullah — Full Stack Web Developer & AI Automation Specialist LinkedIn

About

A malware scanner your AI assistant can actually drive. This plugin turns WordPress into a Model Context Protocol (MCP) server, so an AI assistant such as Claude can scan the site on request, read the files it flags, and explain what it found in plain language. It is strictly read-only.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages