Blog · Security

An Incident Response Plan Sized for a Small Site

Most small WordPress sites do not have a security team. They have an owner, maybe a developer on retainer, and a host. When something goes wrong, that is exactly enough people to handle it well, as long as everyone knows their job in advance. The problem is never staffing. The problem is improvising under pressure.

An incident response plan is not a binder. For a small site it is one page: who does what, in what order, and what not to do. Write it now, while nothing is on fire, and pin it somewhere you can find it in a hurry.

The four phases

Every incident, big or small, moves through the same four phases. Skipping one is how sites get reinfected two weeks after the first cleanup.

  1. Contain. Stop the damage from spreading or continuing.
  2. Investigate. Find out what happened before you erase the evidence.
  3. Recover. Rebuild from a known-clean state.
  4. Communicate. Tell the people who need to know, in the right order.

Containment: stop the bleeding first

The instinct when you discover a hack is to start deleting suspicious files immediately. Resist that for the first few minutes. Containment means limiting damage without destroying the record of what happened.

  • Put the site in maintenance mode or take it offline if it is actively serving malware, spam redirects, or defacement to visitors.
  • Rotate every credential. WordPress admin passwords, database password, SFTP/SSH keys, and any API keys stored in plugins. Assume all of them are compromised.
  • Force a logout of all sessions. A quick way with wp-cli:
wp user list --field=ID | xargs -I{} wp user session destroy {} --all
  • If Cloudflare sits in front of the site, you can lock things down at the edge fast: turn on “Under Attack” mode, tighten WAF rules, or block by country or ASN while you investigate, without touching the origin server yet.
  • Do not restore from backup yet. Restoring too early destroys evidence and, if the backup itself predates the breach point, you can restore the same vulnerability right back in.

Evidence: what to preserve before you clean

You do not need forensic software. You need to not overwrite things. Before any cleanup:

  • Copy the whole site directory and database to a separate location, timestamped. This is your evidence copy, not a working copy.
  • Save the web server and access logs covering as far back as you have them. These show when the attacker got in and what they did.
  • List recently modified files. A quick sweep:
find . -type f -mtime -14 -not -path "./wp-content/cache/*"
  • Diff core files against known-good checksums to see what was tampered with:
wp core verify-checksums
  • List all plugins and themes with versions and cross-check against what should be installed:
wp plugin list
wp theme list
  • Check for unfamiliar admin users, especially ones created recently:
wp user list --role=administrator

Even a rough timeline (“file X changed on this date, unfamiliar admin created two days before that”) tells you the likely entry point, which matters for recovery. If you skip investigation you are just guessing at fixes.

Recovery: rebuild from clean, not from hope

Once you understand roughly what happened, recovery is about certainty, not speed.

  • Reinstall WordPress core, all plugins, and the theme from fresh, official sources. Do not trust existing files even if they look fine.
  • Restore content (posts, pages, media, database) from a backup dated before the compromise, not the most recent one, unless you have confirmed the most recent backup predates the entry point.
  • Update everything to current versions before bringing the site back online. PHP 8.3 with OPcache is a solid, current baseline; run supported plugin and core versions, since old versions are the single most common way sites get hacked in the first place.
  • Change credentials again after recovery, in case any were exposed in the restored files or database.
  • Re-enable caching layers deliberately. Flush LiteSpeed page cache and any Redis or Memcached object cache after recovery so you are not serving cached copies of compromised content.
  • Verify before you announce it fixed. Load the site, check for injected scripts in page source, check for unexpected redirects, and confirm Cloudflare and DNS still point where you expect.

Communication: who to tell, and in what order

Technical cleanup is only half the incident. Who you tell, and when, determines how much trust you keep.

  • Internal first. Whoever owns the site and whoever built it should know within minutes, not after the fix is done.
  • Host or hosting support next, especially if the compromise might affect other sites sharing infrastructure, or if you need help isolating the origin server.
  • Users, if their data was exposed. If the site stores customer information, orders, or account credentials and there is any chance those were accessed, tell affected users plainly: what happened, what data was involved, and what you did about it. Vague reassurance erodes trust faster than a clear, honest note.
  • Search engines and Cloudflare, if the site was flagged. A site serving malware or spam can get blocklisted; request a review once you have confirmed the site is genuinely clean.

Write these communication steps down in advance, with names and contact methods filled in, so no one is drafting an apology email while also trying to remember an SFTP password.

The one-page plan template

Fill this in once, before anything happens, and keep it somewhere accessible outside the site itself:

INCIDENT RESPONSE - [SITE NAME]

Contacts:
  Site owner: ___________  Phone/email: ___________
  Developer/agency: ___________  Phone/email: ___________
  Hosting support: ___________  (account/ticket info)
  Cloudflare account owner: ___________

Containment steps:
  1. Put site in maintenance mode / take offline
  2. Rotate: WP admin, DB, SFTP/SSH, API keys
  3. Force logout all sessions
  4. Enable Cloudflare Under Attack mode if applicable

Evidence to preserve before cleanup:
  - Full site + DB copy (timestamped)
  - Server/access logs
  - wp core verify-checksums output
  - Plugin/theme/user list

Recovery checklist:
  - Fresh core/plugin/theme install from official sources
  - Restore content from pre-incident backup
  - Update all software to current versions
  - Rotate credentials again
  - Flush all caches (page + object)
  - Verify clean before relaunch

Who to notify, in order:
  1. Owner/developer (immediately)
  2. Host (within hours)
  3. Affected users, if data exposure suspected
  4. Search engines / Cloudflare, if flagged

Takeaway

A hack is stressful mainly because it is unfamiliar territory under time pressure. A written plan removes the improvisation: you contain first, preserve evidence before you clean anything, rebuild from known-good sources rather than trusting what is already there, and communicate on a schedule instead of in a scramble. None of this requires a security team. It requires ten minutes now to write down what you would do, so that on the day it matters you are executing a plan instead of inventing one. If your host already handles origin isolation and edge-level attack mitigation for you, that is one less item on your list, but the plan itself is still yours to write.