From wordpress-expert
Scans locally synced WordPress PHP files for malware patterns using grep: obfuscation chains, backdoor signatures, suspicious placements, and dangerous function usage.
npx claudepluginhub dr-robert-li/cowork-wordpress-expertThis skill uses the workspace's default tool permissions.
You perform pattern-based malware and suspicious code detection on locally synced WordPress files. This diagnostic identifies potential security threats through pattern matching without requiring remote server access.
Guides Next.js Cache Components and Partial Prerendering (PPR) with cacheComponents enabled. Implements 'use cache', cacheLife(), cacheTag(), revalidateTag(), static/dynamic optimization, and cache debugging.
Guides building MCP servers enabling LLMs to interact with external services via tools. Covers best practices, TypeScript/Node (MCP SDK), Python (FastMCP).
Generates original PNG/PDF visual art via design philosophy manifestos for posters, graphics, and static designs on user request.
You perform pattern-based malware and suspicious code detection on locally synced WordPress files. This diagnostic identifies potential security threats through pattern matching without requiring remote server access.
IMPORTANT: This is a SEPARATE category from core integrity checking (which uses WP-CLI verify-checksums). This skill scans for suspicious patterns in ALL synced files, not just core files.
This skill scans locally synced WordPress files at .sites/{site-name}/ for four categories of suspicious patterns:
Before running scans, you need:
example-com).sites/{site-name}//connect commandIf the local sync directory doesn't exist or is empty, return an error finding and skip scans.
CRITICAL DISTINCTION: This skill scans LOCAL files at .sites/{site-name}/, NOT remote files via SSH. Files have already been synced by the /connect command. This makes grep operations fast and avoids SSH overhead.
These patterns indicate deliberate code obfuscation, commonly used by malware to hide payloads.
Pattern 1a: eval with base64_decode
grep -rn 'eval\s*(\s*base64_decode' .sites/{site-name}/ --include="*.php"
What it finds: Code that decodes base64 content and immediately executes it with eval(). This is a common malware pattern.
Pattern 1b: Double base64_decode
grep -rn 'base64_decode.*base64_decode' .sites/{site-name}/ --include="*.php"
What it finds: Multiple layers of base64 encoding. Legitimate code rarely needs double encoding.
Pattern 1c: gzinflate/gzuncompress with base64_decode
grep -rn 'gzinflate\s*(\s*base64_decode\|gzuncompress\s*(\s*base64_decode' .sites/{site-name}/ --include="*.php"
What it finds: Compressed AND encoded content. Often used to hide malicious scripts.
Pattern 1d: str_rot13 with eval or base64_decode
grep -rn 'str_rot13.*eval\|str_rot13.*base64_decode' .sites/{site-name}/ --include="*.php"
What it finds: ROT13 encoding combined with execution functions. Another obfuscation technique.
IMPORTANT: Do NOT flag standalone base64_decode without eval/exec/double-encoding. Too many false positives (legitimate uses: email encoding, data URIs, image embedding).
For each match in Category 1:
Finding ID: SUSP-OBFUSCATE-{3-char-md5-of-filepath:line}
Severity: Critical
Category: Suspicious Code
Example Finding:
{
"id": "SUSP-OBFUSCATE-7a9",
"severity": "Critical",
"category": "Suspicious Code",
"title": "Obfuscated code execution detected",
"summary": "This file contains hidden code that decodes and executes itself, a common malware technique.",
"detail": "Found pattern 'eval(base64_decode(' at line 42. Context:\n\n40: // Plugin initialization\n41: function init_plugin() {\n42: eval(base64_decode('ZXZhbCgnZWNobyAi...'));\n43: register_hooks();\n44: }\n\nThis pattern is commonly used by malware to hide malicious code from security scans.",
"location": "wp-content/plugins/suspicious-plugin/init.php:42",
"fix": "Investigate this file immediately. If you did not add this code intentionally, it is likely malware. Compare with the original plugin source from WordPress.org or the theme developer. If confirmed malicious, delete the file and scan for other compromised files. Consider restoring from a clean backup."
}
These patterns match known backdoor and webshell signatures.
Pattern 2a: Common backdoor names (case-insensitive)
grep -rin 'FilesMan\|WSO\|c99shell\|r57shell\|b374k' .sites/{site-name}/ --include="*.php"
What it finds: References to well-known PHP backdoors and webshells.
Pattern 2b: Shell execution with user input
grep -rn 'shell_exec\s*(\s*\$_\|system\s*(\s*\$_\|passthru\s*(\s*\$_' .sites/{site-name}/ --include="*.php"
What it finds: Direct execution of shell commands from user input ($_GET, $_POST, $_REQUEST). Major security risk.
For each match in Category 2:
Finding ID: SUSP-BACKDOOR-{3-char-md5-of-filepath:line}
Severity: Critical
Category: Suspicious Code
Example Finding:
{
"id": "SUSP-BACKDOOR-3c1",
"severity": "Critical",
"category": "Suspicious Code",
"title": "Known backdoor signature detected",
"summary": "This file contains code matching a known malicious backdoor.",
"detail": "Found backdoor signature 'FilesMan' at line 156. Context:\n\n154: <?php\n155: if (isset($_GET['action'])) {\n156: eval(FilesMan($_GET['cmd']));\n157: }\n158: ?>\n\nFilesMan is a known PHP backdoor that allows remote file management and code execution.",
"location": "wp-content/themes/child-theme/functions.php:156",
"fix": "This is a confirmed backdoor. Remove this code immediately. The file may have been compromised. Restore functions.php from a clean backup or the original theme source. After removing, scan the entire site for other infected files and review server access logs for unauthorized access."
}
Example Finding (Shell Execution):
{
"id": "SUSP-BACKDOOR-8d4",
"severity": "Critical",
"category": "Suspicious Code",
"title": "Shell command execution from user input",
"summary": "This file executes system commands directly from user-provided data, allowing code execution.",
"detail": "Found pattern 'system($_GET' at line 23. Context:\n\n21: function run_command() {\n22: $cmd = $_GET['command'];\n23: system($_GET['command']);\n24: }\n\nThis allows an attacker to run arbitrary system commands by visiting a URL like: yoursite.com/file.php?command=rm%20-rf%20/",
"location": "wp-content/plugins/vulnerable-plugin/admin.php:23",
"fix": "Remove this code immediately. If this is a legitimate admin function, rewrite it to use a whitelist of allowed commands and proper authentication. Never execute user input directly. If this is not your code, the plugin is malicious and should be deleted."
}
Files in locations where they shouldn't exist.
Pattern 3a: PHP files in uploads directory
find .sites/{site-name}/wp-content/uploads -name "*.php" -type f 2>/dev/null
What it finds: PHP files in wp-content/uploads/. WordPress uploads directory should only contain media files (images, PDFs, etc.), not executable PHP.
Pattern 3b: Unexpected PHP files in wp-includes/
This requires comparing found PHP files against a known good list of core wp-includes/ files. For v1 implementation:
find .sites/{site-name}/wp-includes -name "*.php" -type f | wc -l
Count total PHP files in wp-includes/. WordPress 6.x core has approximately 400-450 PHP files in wp-includes/. If count is significantly higher (e.g., >500), flag for manual review.
Alternative: Check for files with suspicious names in wp-includes/:
find .sites/{site-name}/wp-includes -name "*.php" -type f | grep -E '(shell|backdoor|c99|wso|eval|exec|system|cmd)'
For each match in Category 3:
Finding ID: SUSP-PLACEMENT-{3-char-md5-of-filepath}
Severity: Warning
Category: Suspicious Code
Example Finding (PHP in uploads):
{
"id": "SUSP-PLACEMENT-5f2",
"severity": "Warning",
"category": "Suspicious Code",
"title": "PHP file found in uploads directory",
"summary": "A PHP script was found in the uploads folder, where only media files belong.",
"detail": "Found PHP file: wp-content/uploads/2024/03/shell.php\n\nThe uploads directory should only contain media files (images, videos, documents). PHP files here can be executed by visiting their URL directly, bypassing WordPress security.",
"location": "wp-content/uploads/2024/03/shell.php",
"fix": "Investigate this file. If you did not upload it intentionally, delete it immediately. Check server access logs to determine how it was uploaded. Consider disabling PHP execution in uploads directory via .htaccess:\n\n<Files *.php>\ndeny from all\n</Files>"
}
Example Finding (Suspicious wp-includes file):
{
"id": "SUSP-PLACEMENT-9a7",
"severity": "Warning",
"category": "Suspicious Code",
"title": "Unexpected file in wp-includes directory",
"summary": "A file with a suspicious name was found in WordPress core directory.",
"detail": "Found file: wp-includes/wp-shell.php\n\nThis file name does not match standard WordPress core files. It may have been added by malware.",
"location": "wp-includes/wp-shell.php",
"fix": "Verify whether this is a legitimate WordPress core file by checking WordPress.org source code for your version. If not found in official source, delete this file and run a full malware scan."
}
Coding patterns that are risky even if not immediately malicious.
Pattern 4a: eval with variable (not string literal)
grep -rn 'eval\s*(\s*\$' .sites/{site-name}/ --include="*.php"
What it finds: eval() with variable input. Even without base64, eval($var) is dangerous if $var comes from user input.
Pattern 4b: assert with variable input
grep -rn 'assert\s*(\s*\$' .sites/{site-name}/ --include="*.php"
What it finds: assert() with variable input. Can be exploited similarly to eval() in older PHP versions.
Pattern 4c: preg_replace with /e modifier (deprecated)
grep -rn 'preg_replace.*\/.*e' .sites/{site-name}/ --include="*.php"
What it finds: preg_replace() with /e modifier, which evaluates matched code. Deprecated since PHP 5.5, removed in PHP 7, commonly exploited.
Pattern 4d: create_function (deprecated)
grep -rn 'create_function' .sites/{site-name}/ --include="*.php"
What it finds: create_function(), deprecated in PHP 7.2, removed in PHP 8.0. Often used in exploits.
For each match in Category 4:
Finding ID: SUSP-DANGEROUS-{3-char-md5-of-filepath:line}
Severity: Warning
Category: Suspicious Code
Example Finding:
{
"id": "SUSP-DANGEROUS-2e8",
"severity": "Warning",
"category": "Suspicious Code",
"title": "Use of deprecated and dangerous function",
"summary": "This code uses a deprecated PHP function that is commonly exploited by attackers.",
"detail": "Found 'create_function' at line 87. Context:\n\n85: function dynamic_callback($input) {\n86: $callback = create_function('$val', 'return $val * 2;');\n87: return array_map($callback, $input);\n88: }\n\ncreate_function() is deprecated (PHP 7.2+) and removed (PHP 8.0+). It uses eval() internally and is commonly exploited for code injection.",
"location": "wp-content/plugins/old-plugin/helpers.php:87",
"fix": "Replace create_function() with an anonymous function (closure):\n\nBefore: $callback = create_function('$val', 'return $val * 2;');\nAfter: $callback = function($val) { return $val * 2; };\n\nIf this plugin is from WordPress.org, check for an updated version."
}
To reduce false positives, apply these filters:
Skip these directories:
node_modules/ — Build tools may use legitimate base64 for datavendor/ — Third-party libraries may have legitimate uses*.min.js — Minified JS often contains legitimate base64 for data URIsImplementation:
# Add --exclude-dir to grep commands
grep -rn 'pattern' .sites/{site-name}/ --include="*.php" \
--exclude-dir=node_modules \
--exclude-dir=vendor \
--exclude='*.min.js'
For base64_decode matches:
For WordPress.org plugins:
Detection:
# Check if file path contains wp-content/plugins/{known-plugin}/
# Known plugins can be detected from previous plugin list check
Return findings as a JSON array. Each finding must include:
id (string) — Deterministic ID: SUSP-{PATTERN_TYPE}-{3-char-md5-of-filepath:line}severity (string) — "Critical" for Categories 1-2, "Warning" for Categories 3-4category (string) — "Suspicious Code" (NOT "Security")title (string) — Short descriptive titlesummary (string) — One non-technical sentence explaining the riskdetail (string) — Technical detail including:
location (string) — Relative file path with line number (e.g., "wp-content/plugins/plugin-name/file.php:123")fix (string) — Specific remediation recommendationExample Complete Output:
[
{
"id": "SUSP-OBFUSCATE-7a9",
"severity": "Critical",
"category": "Suspicious Code",
"title": "Obfuscated code execution detected",
"summary": "This file contains hidden code that decodes and executes itself, a common malware technique.",
"detail": "Found pattern 'eval(base64_decode(' at line 42 in wp-content/plugins/suspicious-plugin/init.php.\n\nContext:\n40: // Plugin initialization\n41: function init_plugin() {\n42: eval(base64_decode('ZXZhbCgnZWNobyAi...'));\n43: register_hooks();\n44: }\n\nThis pattern is commonly used by malware to hide code from security scans.",
"location": "wp-content/plugins/suspicious-plugin/init.php:42",
"fix": "Investigate immediately. Compare with original plugin source. If malicious, delete file and scan for other compromised files."
},
{
"id": "SUSP-PLACEMENT-5f2",
"severity": "Warning",
"category": "Suspicious Code",
"title": "PHP file found in uploads directory",
"summary": "A PHP script was found in the uploads folder, where only media files belong.",
"detail": "Found PHP file: wp-content/uploads/2024/03/shell.php. The uploads directory should only contain media files.",
"location": "wp-content/uploads/2024/03/shell.php",
"fix": "Investigate this file. If not intentionally uploaded, delete immediately. Consider disabling PHP execution in uploads via .htaccess."
}
]
If .sites/{site-name}/ doesn't exist:
{
"id": "SUSP-SYNC-001",
"severity": "Warning",
"category": "Suspicious Code",
"title": "Local files not synced",
"summary": "Cannot perform malware scan because files have not been synced locally.",
"detail": "The local sync directory '.sites/{site-name}/' does not exist. Files must be synced via the /connect command before malware scanning can be performed.",
"location": "Local Sync",
"fix": "Run the /connect command to sync site files locally, then retry this diagnostic."
}
If directory exists but has no PHP files:
{
"id": "SUSP-SYNC-002",
"severity": "Info",
"category": "Suspicious Code",
"title": "No PHP files found to scan",
"summary": "The local sync directory exists but contains no PHP files.",
"detail": "Found 0 PHP files in '.sites/{site-name}/'. This may indicate an incomplete sync or a non-PHP site.",
"location": "Local Sync",
"fix": "Verify the site was synced correctly. Re-run /connect if needed."
}
If grep/find commands fail:
{
"id": "SUSP-CMD-003",
"severity": "Warning",
"category": "Suspicious Code",
"title": "Scan command failed",
"summary": "An error occurred while scanning for suspicious code patterns.",
"detail": "Command 'grep -rn pattern' failed with error: {error_output}. This may indicate file permission issues or corrupted local files.",
"location": "Scan Execution",
"fix": "Check file permissions in '.sites/{site-name}/'. Re-sync files if needed."
}
Malware scan is complete when: