Home/ Blog/ Explainers/ Article
Blog · Explainers

How to Write an Incident Response Plan That Works Under Pressure

How to write an incident response plan: severity levels tied to real alerts, roles, runbooks, pre-approved containment, evidence, and a tested worked example.

Architectural floor plan with one numbered route traced to an exit

To write an incident response plan, decide what counts as an incident, sort incidents into severity levels, name who owns each decision, write a one-page runbook for each attack you are most likely to face, confirm the logs you will need actually exist, pre-approve containment actions, and test the whole thing with a tabletop exercise before you need it.

Think of it like a fire evacuation plan. Nobody reads a binder while the alarm is going off. What saves people is that the exits were chosen in advance, someone was already named to check each floor, and everyone walked the route once during a drill. An incident response plan works the same way. Its job is to move the decisions out of the worst hour of your year and into a calm afternoon, so that when something breaks, people are executing rather than debating.

Most templates online stop at the document. This guide goes one level lower, to the place plans usually fail: the link between the plan and the alerts that start it. We run managed Wazuh for customers, so the examples use real Wazuh rule IDs, a real containment config, and a traced incident from first alert to closed ticket.

What is an incident response plan, and what goes in it?

An incident response plan is a short written agreement about who does what when a security event turns out to be real. It covers scope, severity, roles, contacts, scenario runbooks, evidence handling, communications, and how the plan gets tested and updated. A plan that only lists phases, without names and thresholds, is a policy, not a plan.

The reference most teams start from is NIST. Its incident response guide, SP 800-61 Revision 3, was published in April 2025 and replaced the 2012 Revision 2. The older edition is the one most templates still copy, with its four-phase cycle: preparation; detection and analysis; containment, eradication, and recovery; and post-incident activity. Revision 3 recasts the guidance as a Community Profile of the NIST Cybersecurity Framework (CSF) 2.0, which treats incident response as part of everyday risk management instead of a separate emergency drill. In plain terms: the plan should connect to how you already run and monitor systems, not sit in a folder.

SectionWhat it answersThe test it must pass
Scope and definitionsWhich systems and data are covered, and what an "incident" isTwo people classify the same event the same way
Severity matrixHow bad is it, and how fast do we moveEvery level has a response time and a named owner
Roles and contactsWho leads, who decides, who talks to whomReachable when company email and chat are down
Scenario runbooksThe first concrete steps for your likely attacksA new hire could start step one alone
Evidence and loggingWhat records exist and how long they are keptRetention is longer than a realistic detection delay
Containment authorityWho may block, disable, or isolate without a meetingWritten down before the incident, not during
CommunicationsCustomers, regulators, insurers, staffLegal deadlines are listed with their clock start
Testing and reviewWhen the plan is exercised and updatedDated proof of the last exercise
The eight sections a working plan needs, with the check we use to decide whether each section is real. Structure informed by NIST SP 800-61r3.

How do you write an incident response plan, step by step?

Write it in the order below, because each step depends on the one before it. You cannot set response times until you have severity levels, and you cannot write runbooks until you know who is allowed to act.

Step 1: Define an incident and set severity levels

Start with one sentence that defines an incident for your organization, for example: "any event that threatens the confidentiality, integrity, or availability of customer data or production systems." Then create three or four severity levels, each with a response time and an owner.

Here is where most plans go vague. They say "monitor the SIEM" and stop. A SIEM, or security information and event management system, is the tool that collects logs from your servers and raises alerts (our plain-English SIEM explainer covers it). Wazuh scores every alert on a scale from 0 to 15, as described in the Wazuh rule classification table: level 10 covers repeated failed logins, level 11 integrity warnings such as a modified system binary, and level 15 a severe attack. Tie your severity levels to those numbers so the plan starts from the same signal your monitoring produces.

SeverityTypical triggerResponse timeWho is involved
SEV-1 CriticalConfirmed compromise of production or customer data; alert level 12 to 15 that a human confirmsPage now, start within 15 minutesIncident lead, system owner, management, legal
SEV-2 HighLikely compromise of one host or account, such as a login that succeeds right after a brute-force burstWithin 1 hourIncident lead, system owner
SEV-3 MediumAttack attempts with no sign of success; level 10 brute force that was blockedSame business dayOn-call engineer
SEV-4 LowIsolated alerts below level 10 with no follow-on activityWeekly reviewWhoever tunes detections
A starting severity matrix (illustration). The alert level is an input; the person on call assigns the final severity based on business impact.

Note the SEV-2 row. A successful SSH login is only level 3 in Wazuh, a routine "authorized event." It becomes the most important line in your logs when it arrives from the same address that just failed forty times. Severity is about context, and your matrix should say so.

Step 2: Name the roles and build a contact sheet that works offline

Every incident needs one incident lead who makes decisions, even in a team of three. Name a primary and a backup for that role, plus an owner for each critical system and one person who handles outside communication.

Put phone numbers on the sheet, not just chat handles. If an attacker is inside your email tenant, the incident cannot be coordinated on that email. Keep a printed copy and a copy outside your main cloud account.

Step 3: Write one-page runbooks for your likely incidents

Pick the four or five incidents you are actually likely to face, not the full catalog. For a small company running Linux servers, that is usually a compromised account, ransomware, a compromised web application, a lost or stolen laptop, and accidental data exposure. Each runbook gets a trigger, the first five actions, and the condition for escalating.

Here is a skeleton you can paste into your wiki and fill in:

ir-plan.md · plan skeleton
# Incident Response Plan (v1, owner: NAME, last tested: DATE)
## 1. Scope
Systems: ...   Data: ...   Out of scope: ...
## 2. Definition
An incident is ...
## 3. Severity
SEV-1 | trigger | 15 min | lead + owner + mgmt + legal
SEV-2 | trigger | 1 h    | lead + owner
SEV-3 | trigger | same day | on-call
SEV-4 | trigger | weekly | detection owner
## 4. Roles and contacts (phone first)
Incident lead: NAME, PHONE   Backup: NAME, PHONE
Comms: NAME, PHONE   Legal/insurer: NAME, PHONE
## 5. Runbooks
5.1 Compromised account   5.2 Ransomware   5.3 Web app compromise
5.4 Lost device   5.5 Data exposure
## 6. Pre-approved containment
Block source IP: on-call, no approval needed
Disable user account: on-call, tell lead within 15 min
Isolate production host: lead only
## 7. Evidence
Log sources, retention period, where copies go, who holds them
## 8. Notification deadlines
Regulator, clock start, owner
## 9. Testing
Next tabletop: DATE   Review after every SEV-1 or SEV-2

Step 4: Make sure the evidence will exist

A plan is only as good as the records behind it. Before you finalize anything, check three things: which systems actually send logs, how long those logs are kept, and whether a copy lives somewhere an attacker on the affected host cannot delete.

Retention is the quiet failure. Intruders often go unnoticed for weeks, so if your alerts are kept for 30 days and the first sign of trouble is a month old, the trail you need is already gone. On a Wazuh server, alerts are written to /var/ossec/logs/alerts/alerts.json and rotated into dated archives under the same directory. Check what you really have:

terminal · on the Wazuh server
sudo ls /var/ossec/logs/alerts/
sudo du -sh /var/ossec/logs/alerts/

Also check how long the Wazuh indexer, the searchable store behind the dashboard, keeps alert indices. That is set by an index lifecycle policy you configure, so write the real number into the plan rather than an assumption.

Step 5: Pre-approve containment actions

Decide now which actions the on-call person may take without asking anyone. Blocking an attacking IP address is low risk and should be automatic. Disabling an account is medium risk. Pulling a production server offline is a business decision, so it belongs to the incident lead.

Wazuh can carry out the low-risk tier for you through active response, which runs a script on the affected host when a rule fires. The firewall-drop command ships in the default server configuration. This block, added to /var/ossec/etc/ossec.conf on the Wazuh server, blocks any address that trips the two SSH brute-force rules for ten minutes (option reference: Wazuh active response settings):

/var/ossec/etc/ossec.conf · on the Wazuh server
<ossec_config>
  <active-response>
    <disabled>no</disabled>
    <command>firewall-drop</command>
    <location>local</location>
    <rules_id>5712,5763</rules_id>
    <timeout>600</timeout>
  </active-response>
</ossec_config>

Rule 5712 fires on repeated logins with a username that does not exist, and rule 5763 on repeated failed passwords, each after eight matching failures from one address within two minutes, per the rule definitions. Add your office and VPN addresses as <white_list> entries in the <global> section of the same file so you never block yourself, then restart the manager with sudo systemctl restart wazuh-manager. For when automation helps and when it hurts, see using Wazuh for endpoint response.

List every party you may have to tell, and the deadline for each. If you handle personal data of people in the EU, Article 33 of the GDPR requires you to notify the supervisory authority of a personal data breach within 72 hours of becoming aware of it, where feasible. Your cyber insurer, contracts with customers, and sector rules may set their own clocks. Write who owns each notification, and keep a holding statement drafted so nobody writes one from scratch at 3 a.m.

Step 7: Test it with a tabletop exercise

A tabletop exercise is a meeting where you walk a made-up incident through the plan, out loud, step by step. It takes about an hour, and it finds the gaps cheaply: the backup lead who left the company, the runbook that assumes access nobody has. Run one before you call the plan finished, then at least once a year and after every SEV-1 or SEV-2.

A worked example: tracing one alert through the plan

Here is the exact scenario we use as a first tabletop, because it exercises severity, containment, and evidence in under an hour. It is an illustrative alert built on real Wazuh rule IDs.

1. The alert. At 03:14 the Wazuh server raises rule 5763 against a web server called web-01. A trimmed copy of the alert looks like this:

alerts.json · one alert, trimmed
{
  "timestamp": "2026-10-27T03:14:09.512+0000",
  "rule": {
    "level": 10,
    "id": "5763",
    "description": "sshd: brute force trying to get access to the system. Authentication failed.",
    "mitre": { "id": ["T1110"], "technique": ["Brute Force"] }
  },
  "agent": { "id": "003", "name": "web-01" },
  "data": { "srcip": "203.0.113.45", "dstuser": "deploy" }
}

The MITRE ATT&CK tag T1110 names the technique, password guessing (our MITRE ATT&CK explainer covers how those tags work). On its own this is SEV-3: an attempt, already blocked by the active response from Step 5.

2. The question that changes severity. The runbook's first action is "check whether any login from this address succeeded." It uses jq, a JSON filter (apt install jq or dnf install jq if missing); for older incidents, pipe the dated archives from Step 4 through zcat into the same filter. On the Wazuh server:

terminal · on the Wazuh server
sudo jq -c 'select(.rule.id=="5715" and .data.srcip=="203.0.113.45") | {timestamp, host: .agent.name, user: .data.dstuser}' /var/ossec/logs/alerts/alerts.json
output
{"timestamp":"2026-10-27T03:13:51.204+0000","host":"web-01","user":"deploy"}

Rule 5715 is a successful SSH login. One line came back, eighteen seconds before the brute-force alert. The attacker got in as deploy before the block landed. Per the matrix, this is now SEV-2: page the incident lead.

3. Contain. Disabling an account is pre-approved for on-call, so the engineer locks it on web-01 and confirms the block is in place:

terminal · on web-01
sudo usermod --lock --expiredate 1 deploy
sudo pkill -KILL -u deploy
sudo iptables -S | grep 203.0.113.45

The Wazuh server also records rule 651, "Host Blocked by firewall-drop Active Response," which proves the automatic step ran and when.

4. Preserve evidence. Before anyone cleans up, copy the records off the host and fingerprint them, so you can later show they were not altered:

terminal · on web-01
sudo mkdir -p /root/ir-20261027
sudo cp /var/log/auth.log /home/deploy/.bash_history /home/deploy/.ssh/authorized_keys /root/ir-20261027/
sudo sh -c 'cd /root/ir-20261027 && sha256sum * > SHA256SUMS'

On RHEL-family hosts such as AlmaLinux, the SSH log is /var/log/secure instead of /var/log/auth.log. Then move that folder to storage outside the server. Our test usually finds the gap right here: there is no agreed place for evidence, so the runbook gets a line naming one.

5. Decide and close. The lead reviews the shell history and finds a new key in authorized_keys. That is persistence, so the host is rebuilt from a known-good image rather than cleaned, the password policy for service accounts changes, and the ticket closes with a short review: what fired, what we did, and the one change to the plan.

Where incident response plans break

Plans rarely fail because a section is missing. They fail at the seams between the document and the real systems. These are the failures we see most:

  • The plan lives on the system that is down. A plan stored only in the company wiki is unreadable during a ransomware event that took the wiki with it.

  • Severity follows the alert number blindly. As the example showed, the dangerous event was a level 3 success, not the level 10 failure. A matrix keyed only to alert levels sends the real incident to the weekly review.

  • Automatic blocking catches the wrong address. If your servers sit behind a load balancer or a content delivery network, the address Wazuh sees may be the proxy, and blocking it takes down your own traffic. Test active response against your real network path before you trust it.

  • Logs exist on the box the attacker controls. An intruder with root can delete local logs. The copy that matters is the one already shipped to a separate server.

  • Nobody retests after the team changes. The named backup lead leaves, and the plan silently loses its second pair of hands. Put "last tested" on the first line so a stale plan is obvious.

Noisy alerts also train people to ignore pages, so test your rules with wazuh-logtest before a plan depends on them. If you would rather not run the detection side yourself, our incident response page explains how we approach it.

How long should an incident response plan be?

For a small or mid-sized company, ten to fifteen pages is plenty: a few pages for scope, severity, roles, and contacts, then one page per runbook. If it runs past thirty pages, people will not read it under pressure. Short and tested beats long and untouched every time.

Topics

Frequently asked questions

What should an incident response plan include?

An incident response plan should include its scope, a definition of an incident, severity levels with response times, named roles and phone contacts, one-page runbooks for likely attacks, evidence and log retention, pre-approved containment actions, notification deadlines, and a testing schedule.

What are the phases of incident response?

NIST SP 800-61 Revision 2 described four phases: preparation; detection and analysis; containment, eradication, and recovery; and post-incident activity. Revision 3, published in April 2025, recasts the guidance as a Community Profile of the NIST Cybersecurity Framework 2.0, so incident response becomes part of everyday risk management.

How often should you test an incident response plan?

Run a tabletop exercise before you call the plan finished, then at least once a year and after every SEV-1 or SEV-2 incident. A tabletop is a meeting where you walk a made-up incident through the plan step by step. It takes about an hour.

How long should an incident response plan be?

For a small or mid-sized company, ten to fifteen pages is plenty: a few pages for scope, severity, roles, and contacts, then one page per runbook. Past thirty pages, people will not read it under pressure.

Should incident containment be automated?

Only for low-risk actions. Blocking an attacking IP address can be automatic, for example with Wazuh active response. Disabling an account can be pre-approved for the on-call engineer. Taking a production server offline is a business decision, so it belongs to the incident lead.

See what Suriq finds on your own servers.

Agentless checks for uptime and your cloud, a lightweight agent for detection on each server, and one console that ranks and explains what it finds.