WP-Narcan
For the morning after your WordPress site gets hacked. WP-Narcan rebuilds the site from clean, verified sources into a new folder next to the old one, and sets aside anything it can't check, so you can look everything over before you swap it in.
Python · v2.0 · MIT License
$ wpnarcan /var/www/example.comWP-Narcan 2.0.0 (Hopscotch)Site /var/www/example.comWordPress 7.0.6, en_US, single siteOutput /var/www/example.com-rebuiltReport /var/www/example.com-rebuilt-reportWP-Narcan only reads /var/www/example.com.Write the rebuild and report to the places above? [y/N] yWordPress core Downloading WordPress 7.1.2 (en_US) Verified the download's SHA-1 and 3,782 file checksums Old core files (checked against WordPress 7.0.6): 1 modified modified wp-includes/functions.phpPlugins (4) akismet 5.7 -> 5.7.2 wordpress.org, verified contact-form-7 6.0.6 -> 6.1.7 wordpress.org, verified old copy: 1 modified, 1 added (contact-form-7 6.0.6) display-widgets 2.6 set aside: closed on wordpress.org (2021-01-30, Security Issue) woo-extras 3.1 set aside: not on wordpress.orgThemes (2) example-child 1.0 set aside: not on wordpress.org twentytwentyfive 1.5 wordpress.orgMust-use plugins, drop-ins and other files set aside wp-content/mu-plugins/wp-cache-helper.php: must-use plugin (WordPress runs these on every page) [3 suspicious]Uploads Copied 1,284 files (412 MB). Left out 2. wp-content/uploads/2024/03/cache.ico (contains PHP code) wp-content/uploads/2025/11/photo.php.jpg (hidden .php extension) Kept 2 .htaccess files that only block access (WooCommerce, Wordfence and others use them).wp-config.php set aside wp-config.php: 2 suspicious lines, so it wasn't put in the rebuild [2 suspicious] line 74 base64_decode() is often used to hide code line 74 eval() runs a string as PHP codeSummary Rebuilt into /var/www/example.com-rebuilt WordPress 7.1.2 (was 7.0.6) Plugins/themes 3 of 6 came from clean sources Set aside 5 items for you to review in /var/www/example.com-rebuilt-report/review Old site 2 files or folders show signs of tampering (the rebuild doesn't use them) Left out 2 files from uploads Not included the database. WP-Narcan never touches it, and can't tell you how the attacker got in.Done, but some things need your attention (listed above).Read /var/www/example.com-rebuilt-report/NEXT-STEPS.txt before you swap the rebuild in.An example run. Your site will have its own list of plugins.
How It Works
- 01
Checks It's WordPress
Works out the version, the language, whether it's multisite, and where wp-config.php and the content folder are. It reads wp-config.php, so a renamed wp-content turns up by itself.
- 02
Fresh, Verified Core
Downloads WordPress and checks the zip and every file against wordpress.org's checksums, then tells you which of the old core files were changed or shouldn't be there.
- 03
Clean Plugins and Themes
Fresh copies from your own zips or wordpress.org, checked against the published checksums once it's sure they're the same plugin. Plugins wordpress.org has closed aren't installed, because they may be how the attacker got in.
- 04
Sets Aside What It Can't Check
Must-use plugins, drop-ins, custom themes, stray PHP files and a wp-config.php with suspicious code go into a review folder with the reasons, not into the rebuild.
- 05
Uploads, Minus Anything That Runs
Leaves out scripts, photo.php.jpg-style double extensions, images and icons with PHP inside, SVGs with scripts and symbolic links. Keeps the .htaccess files that protect private downloads.
- 06
A Report and Next Steps
Writes a standard .htaccess so permalinks keep working, and puts a report next to the rebuild, never inside it: a summary, report.json, the full log and NEXT-STEPS.txt.
Try It Here
The Config Check
One step of a rebuild is reading wp-config.php for things that shouldn't be there. This is that check, with the same 19 patterns the script uses, running in your browser. Paste a config in, or try the dodgy one I made earlier.
What It Won't Do
- It doesn't touch your database. Rogue admins and injected posts live there; NEXT-STEPS.txt has the queries to find them, but the cleaning is up to you.
- It won't tell you how the attacker got in, though the report points at what was tampered with.
- It can't download paid plugins or themes. Give it the zips, or they're set aside for you to replace.
- It doesn't prove the set-aside code is safe. Its checks are hints for a person, not a malware scanner.
- It doesn't copy caches, backups or logs. It lists them, and you should take them off the server too.
- It won't replace your live site. You do that, after you've checked the rebuild.
Running It
You need Python 3.9 or newer (or Docker) and a copy of the hacked site's files. The rebuild lands next to the original in a folder ending in -rebuilt, with the report beside it in -rebuilt-report.
# Install it (you get a wpnarcan command)$ pip install git+https://github.com/ReignOfComputer/WP-Narcan.git# A dry run first: it checks everything and writes nothing$ wpnarcan /path/to/hacked-site --dry-run# Then the real thing$ wpnarcan /path/to/hacked-site# Paid plugins? Hand it your zips$ wpnarcan /path/to/hacked-site \$ --local-repo-plugins /path/to/plugin-zips \$ --local-repo-themes /path/to/theme-zips# No Python? Build the image in a copy of the repo,# then run it from the folder your site is in$ docker build -t wpnarcan .$ docker run --rm -it -v "$PWD:/work" wpnarcan /work/public_htmlRather Not Do It Yourself?
I clean up hacked WordPress sites, database included, and harden them afterwards.