A PHP script that recursively scans all subdirectories of a WordPress installation and removes malicious .htaccess files injected by malware — without touching legitimate ones created by plugins, themes, or server configuration.
Most cleanup scripts delete every .htaccess they find, which risks breaking:
- Backup plugin rules (e.g. UpdraftPlus, BackupBuddy)
- WooCommerce upload folder protection
- Cache plugin configurations
- Custom server security rules
This script fingerprints files by their content, only deleting ones that match known malware signatures — leaving everything else untouched.
The script currently detects two known variants:
Variant 1 — single quotes, no phtml:
<FilesMatch '.(py|exe|php|PHP|Php|PHp|pHp|pHP|pHP7|PHP7|phP|PhP|php5|suspected)$'>Variant 2 — double quotes, includes phtml:
<FilesMatch ".(py|exe|phtml|php|PHP|Php|PHp|pHp|pHP|pHP7|PHP7|phP|PhP|php5|suspected)$">If you discover new variants, add them to the $malwareSignatures array in the script.
Open cleanup.php and change CHANGE_THIS_SECRET to a random private string only you know.
Upload cleanup.php to your WordPress root — the same folder as wp-config.php.
https://yoursite.com/cleanup.php?key=YOUR_SECRET
Review the output carefully:
- ✅ Would delete — confirm these are all malware files
⚠️ Skipped — confirm your legitimate.htaccessfiles are safe
https://yoursite.com/cleanup.php?key=YOUR_SECRET&dry=0
Delete cleanup.php from your server immediately after running.
Don't stop at .htaccess files — malware often leaves traces elsewhere:
- Change all WordPress, database, FTP, and hosting passwords
- Update WordPress core, all plugins, and all themes
- Check
wp-config.phpfor injected or obfuscated code - Restore your root
.htaccessfrom a backup if tampered with (WordPress needs it for permalinks) - Scan with Wordfence or MalCare
- Check cPanel / hosting file manager for unfamiliar files in
public_html
- The script is protected by a secret key — never leave it with a guessable key
- Always take a full backup before running any automated deletion script
- The dry run mode is there for a reason — always use it first
- Remove the script from your server as soon as you're done
MIT — free to use, share, and modify.