NIS2 Art.21(2)(b): Incident Handling — Internal Response Framework for SaaS Developers (2026)
Security incidents are inevitable. What separates compliant organisations from non-compliant ones under NIS2 is not whether incidents occur — it is whether there are documented, tested, and operational procedures to detect, contain, and recover from them before they cause significant impact.
NIS2 Art.21(2)(b) requires essential and important entities to have "policies and procedures regarding incident handling." This is distinct from Art.23, which governs external reporting to national competent authorities (NCAs). Art.21(2)(b) is the internal obligation — building the incident response (IR) capability itself. Without it, Art.23 reporting becomes meaningless, because you will have no coherent picture of what happened to report.
NCA audits beginning June 2026 will scrutinise both dimensions. Entities that have only reactive, undocumented incident response will face findings. This guide builds the Art.21(2)(b) framework from the ground up for SaaS development teams.
1. Art.21(2)(b) in the Full NIS2 Context
NIS2 Art.21(2) mandates ten cybersecurity risk-management measures. Art.21(2)(b) is the second — and the foundation that most other measures depend on.
The Ten Mandatory Measures
| Subparagraph | Requirement | Primary Owner |
|---|---|---|
| Art.21(2)(a) | Risk analysis and information system security policies | CISO / Management |
| Art.21(2)(b) | Incident handling | SOC / DevSecOps |
| Art.21(2)(c) | Business continuity, backup management, disaster recovery | Ops / SRE |
| Art.21(2)(d) | Supply chain security | Procurement / DevSecOps |
| Art.21(2)(e) | Security in acquisition, development and maintenance (see SDL guide) | Engineering |
| Art.21(2)(f) | Policies to assess effectiveness of cybersecurity measures | Audit / GRC |
| Art.21(2)(g) | Basic cyber hygiene and training | HR / Security Awareness |
| Art.21(2)(h) | Cryptography and encryption policies (see cryptography guide) | Architecture |
| Art.21(2)(i) | HR security, access control, asset management (see access control guide) | IT / HR |
| Art.21(2)(j) | Multi-factor authentication and continuous authentication (see MFA guide) | IT / IAM / Engineering |
Art.21(2)(b) sits at the operational core. When a security event occurs, it is Art.21(2)(b) processes that activate — pulling together logging from Art.21(2)(e) SDL controls, authentication telemetry from Art.21(2)(j) MFA systems, and feeding findings into the Art.23 reporting obligation if the incident crosses the notification threshold.
The Exact Regulatory Text
Art.21(2)(b) requires:
"policies and procedures regarding incident handling"
The Recital 89 of NIS2 clarifies that incident handling should cover "detection, analysis, containment and response." ENISA's Technical Guideline on Incident Handling (2023) expands this to a six-phase lifecycle that NCA auditors use as their assessment reference.
Art.21(2)(b) vs Art.23: The Critical Distinction
Many organisations conflate incident handling with incident reporting. They are related but separate obligations:
| Dimension | Art.21(2)(b) Incident Handling | Art.23 Incident Reporting |
|---|---|---|
| Scope | ALL security events (including those you resolve internally) | Only "significant incidents" with major impact |
| Audience | Internal teams | National competent authorities (NCA), CSIRT |
| Timeline | Ongoing, continuous process | 24h early warning → 72h detailed notification → 1-month final report |
| Documentation | Internal logs, post-mortems, runbooks | Formal notification templates |
| Audit evidence | IR policies, runbooks, log samples, post-mortems | Notification records (if applicable) |
The relationship: Art.21(2)(b) processes generate the intelligence needed for Art.23 reporting. An entity without Art.21(2)(b) cannot accurately assess whether Art.23 thresholds have been crossed — and will either over-report (regulatory burden) or under-report (enforcement risk).
2. The NIS2-Compliant IR Lifecycle
Based on ENISA's 2023 guidelines and NCA audit frameworks, a compliant Art.21(2)(b) process covers six phases. Each phase has specific NIS2 obligations.
Phase 1: Preparation
Preparation is the only phase that happens before an incident. Most Art.21(2)(b) findings in NCA audits are preparation failures.
NIS2 preparation requirements:
- Written IR policy with scope, roles, escalation paths, and review cadence
- IR team with defined responsibilities (not just names — roles and decision authority)
- Contact list for internal responders, external forensics, legal, and NCAs
- Asset inventory current enough to scope an incident (what systems, what data, what impact)
- Playbooks for the most likely incident types (ransomware, data breach, supply chain compromise, DDoS)
- Communication templates pre-approved by legal for internal and external use
- IR tooling deployed and tested (SIEM, EDR, forensic collection)
Proportionality: Art.21(2) applies "taking into account all relevant factors" including entity size and risk exposure. For smaller essential entities, a 10-page IR policy plus three playbooks may suffice. For large essential entities, NCAs expect mature SOC integration and practiced tabletop exercises.
Phase 2: Detection and Identification
NIS2 requires proactive detection capability — waiting for users to report incidents does not satisfy Art.21(2)(b).
Detection sources to implement:
| Source | What It Detects | NIS2 Relevance |
|---|---|---|
| SIEM (log aggregation) | Anomalous access patterns, failed auth spikes, data exfiltration indicators | Primary detection layer |
| EDR / XDR | Malware execution, lateral movement, privilege escalation | Endpoint threats |
| Network monitoring (NDR) | C2 traffic, unusual data flows, scanning | Network threats |
| Application monitoring | Abnormal API usage, injection attempts, account takeover patterns | Application threats |
| Cloud-native monitoring | IAM misuse, storage access anomalies, compute anomalies | Cloud threats |
| Third-party alerts | Threat intelligence feeds, dark web monitoring, CSIRT advisories | External signals |
| User reports | Phishing emails, suspicious activity, social engineering | Human signals |
Classification: Not every alert is an incident. A compliant process distinguishes:
- Event: An observable system occurrence (login failure, firewall block)
- Alert: An event matching a detection rule (100 login failures in 60 seconds)
- Incident: A confirmed or suspected security breach, violation, or compromise
Phase 3: Analysis and Scoping
Once an event is classified as a probable incident, the analysis phase determines what happened, what was affected, and whether Art.23 thresholds are approached.
NIS2 scoping questions:
- What systems and data are affected?
- What is the impact on service continuity? (threshold for Art.23)
- Are other entities affected? (particularly relevant for essential entities with downstream dependencies)
- Is there evidence of data exfiltration? (GDPR Art.33/34 may also apply)
- What is the attack vector and is it still active?
- What is the likely threat actor category?
Art.23 threshold assessment: A "significant incident" under NIS2 has "a major impact on the provision of services." Indicators include:
- More than 5% of active users affected
- Service unavailability exceeding 30 minutes for essential services
- Data integrity of critical data compromised
- Incident affects other essential/important entities
Phase 4: Containment
Containment stops the incident from spreading while preserving forensic evidence. A common failure is destroying evidence during containment (wiping systems instead of isolating them).
NIS2-aware containment principles:
| Action | When | Evidence Consideration |
|---|---|---|
| Network isolation (firewall rules, VLAN) | Active threat spreading | Preserves system state |
| Account suspension / password reset | Compromised credentials | Preserve auth logs before action |
| Service shutdown | Active data exfiltration | Document decision rationale |
| System snapshot / disk image | Before remediation | Mandatory for forensic integrity |
| Container/pod isolation | Kubernetes threats | kubectl cordon, evict, then investigate |
| API key rotation | Compromised service credentials | Generate new, invalidate old in sequence |
Documentation during containment: Every containment action must be timestamped and attributed. NCA auditors examine timelines — gaps in documentation imply either delayed response or poor process.
Phase 5: Eradication and Recovery
Eradication removes the threat. Recovery restores normal operations. These phases often overlap but must be sequenced correctly — recovery before complete eradication leads to re-infection.
Eradication checklist:
- Remove malware, backdoors, or persistence mechanisms confirmed during analysis
- Revoke all credentials and tokens from affected scope (not just the obvious ones)
- Patch the vulnerability that enabled the incident (if known)
- Remove unauthorised access paths (rogue IAM roles, SSH keys, firewall exceptions)
- Clean up attacker-created resources (cloud instances, storage buckets, user accounts)
Recovery verification: Before returning to production, verify:
- Integrity of restored data against pre-incident baselines
- No residual indicators of compromise (IoCs) in logs
- All containment measures removed (isolated network segments reconnected)
- Monitoring enhanced for recurrence detection
Phase 6: Post-Incident Review
NIS2 Art.21(2)(b) implicitly requires a feedback loop — the "policies and procedures" must improve over time. NCAs expect post-incident reviews (PIRs) for all significant incidents.
PIR minimum content:
- Timeline of events (from first evidence to resolution)
- Detection quality: how was the incident found, how long did it take
- Response quality: what went well, what was slow
- Root cause analysis
- Lessons learned mapped to specific policies/controls
- Remediation items with owners and deadlines
- Update required to playbooks, detection rules, or policies
3. SIEM Integration for NIS2 Compliance
A SIEM is not mandatory under NIS2, but it is the most common way to demonstrate Art.21(2)(b) compliance for essential entities. NCA auditors from Germany (BSI), Netherlands (NCSC-NL), and Austria (CERT.at) all reference centralised logging as evidence of detection capability.
Minimum Log Sources for NIS2 Art.21(2)(b)
| Log Category | Sources | Retention |
|---|---|---|
| Authentication | IdP (Okta, Azure AD, Auth0), SSH, VPN, privileged access | 12 months minimum |
| Network traffic | Firewall, load balancer, CDN | 6 months minimum |
| Application access | API gateway, application logs, admin panel | 12 months minimum |
| Cloud activity | AWS CloudTrail, Azure Activity Log, GCP Audit Logs | 12 months minimum |
| Endpoint | EDR agent telemetry, system logs | 6 months minimum |
| Change management | Configuration changes, deployments, IAM changes | 24 months minimum |
Retention note: NIS2 does not specify log retention periods, but ENISA's guidelines and NCA audit practice reference 12 months for most categories. GDPR log retention must be balanced against data minimisation — log what you need, not everything.
Detection Rules Aligned to NIS2 Art.21(2)
These SIEM rules detect violations of multiple Art.21(2) controls simultaneously:
# NIS2 Art.21(2)(b) SIEM Detection Rules
# Compatible with Sigma rule format (translates to Splunk/Elastic/QRadar)
# Rule 1: Brute force against privileged accounts (Art.21(2)(j) + Art.21(2)(b))
title: NIS2 — Privileged Account Brute Force
status: production
description: >
Detects rapid authentication failures against accounts in privileged groups.
Triggers Art.21(2)(b) investigation and potential Art.23 assessment.
detection:
selection:
event.action: authentication_failure
user.group: [administrators, domain-admins, cloud-admins]
timeframe: 5m
condition: selection | count(user.name) by user.name > 10
falsepositives:
- Automation scripts with expired credentials
- Password spraying from external IP ranges (check source.ip)
level: high
tags:
- nis2.art21.2j # MFA requirement
- nis2.art21.2b # Incident handling trigger
# Rule 2: Impossible travel (Art.21(2)(b) — anomalous access)
title: NIS2 — Impossible Travel Login
status: production
description: >
Same account authenticated from geographically impossible locations within 2 hours.
Indicates credential theft. Triggers Art.21(2)(b) incident process.
detection:
selection:
event.action: authentication_success
condition: |
selection
| bucket(user.name, span=2h)
| where distinct_count(source.geo.country_iso_code) >= 2
| where geo_distance_km(locations) > 500
level: critical
tags:
- nis2.art21.2b
# Rule 3: Data exfiltration indicator (Art.21(2)(b) — detection)
title: NIS2 — Anomalous Data Transfer Volume
status: production
description: >
Network egress 10x above 30-day baseline for a given service/user.
Potential data exfiltration. Immediate Art.21(2)(b) investigation required.
detection:
selection:
event.type: network_flow
network.direction: egress
condition: |
selection
| rolling_baseline(destination.bytes, window=30d, multiplier=10)
| where destination.bytes > baseline_threshold
level: high
tags:
- nis2.art21.2b
- gdpr.art33 # Potential data breach
# Rule 4: Supply chain indicator — unexpected service account behaviour
title: NIS2 — Service Account Anomalous Access
status: production
description: >
Service account accessing resources outside its normal scope.
Potential supply chain compromise (Art.21(2)(d)) requiring Art.21(2)(b) response.
detection:
selection:
user.type: service_account
event.action: resource_access
condition: |
selection
| where resource.name not in account_baseline_resources(user.name, window=90d)
level: high
tags:
- nis2.art21.2b
- nis2.art21.2d # Supply chain
4. IR Playbook Template for SaaS Entities
NIS2 NCA auditors expect playbooks for the highest-probability incident types. The following template structure covers the three most common categories for SaaS providers.
Playbook: Credential Compromise / Account Takeover
Trigger: Detection rule fires for impossible travel, brute force success, or user reports unexpected access.
Severity Assessment:
- P1 (Critical): Privileged account compromised (admin, IAM, database)
- P2 (High): Standard employee account with access to customer data
- P3 (Medium): External customer account without production access
Response Steps:
| Step | Action | Owner | Timeframe |
|---|---|---|---|
| 1 | Confirm incident (rule true positive vs false positive) | On-call security | 15 min |
| 2 | Identify affected account scope (what can this account access?) | On-call security | 30 min |
| 3 | Suspend account, invalidate all active sessions | Identity team | 30 min |
| 4 | Preserve auth logs (export before any cleanup) | Security / DevOps | 30 min |
| 5 | Determine if data was accessed or exfiltrated | Security analyst | 2 hours |
| 6 | Assess Art.23 threshold (significant impact?) | CISO / Legal | 2 hours |
| 7 | Notify affected user, initiate password reset + MFA re-enrolment | Identity team | 4 hours |
| 8 | If Art.23 threshold met: prepare 24h early warning | Legal / Compliance | 24 hours |
| 9 | Root cause analysis: how was the account compromised? | Security analyst | 48 hours |
| 10 | Playbook update if new attack vector identified | Security team | 5 days |
Playbook: Ransomware / Destructive Malware
Trigger: EDR detection of ransomware behaviour, mass file encryption, or ransom note.
P1 — Immediate Actions (first 30 minutes):
- Activate IR team (all responders on call)
- Network isolation of affected systems (block outbound, preserve east-west)
- Snapshot all affected systems before any remediation
- Assess blast radius: how many systems show encryption activity?
- Identify patient zero (first affected system)
- Confirm backup integrity is intact and isolated from affected network
Art.23 Assessment: Ransomware affecting production systems of essential entities almost always triggers Art.23. Prepare 24h early warning immediately upon P1 classification.
Playbook: Data Exfiltration / Breach
Trigger: Large-scale data access patterns, customer reports of data exposure, dark web notification, SIEM rule for anomalous egress.
Key question sequence:
- What data was accessed? (classification: personal data, health data, financial data)
- How much data? (number of records, data subjects)
- Was data copied externally? (exfiltration confirmed vs suspected)
- Is the access still active? (ongoing breach vs historical)
- GDPR Art.33 applies? (personal data breach → 72h to DPA if risk to individuals)
- NIS2 Art.23 applies? (significant impact on service provision?)
Note: GDPR Art.33 and NIS2 Art.23 can both apply simultaneously. The NIS2+GDPR Dual Reporting guide covers how to manage parallel notification obligations.
5. Python NIS2IncidentHandler
#!/usr/bin/env python3
"""
NIS2IncidentHandler — Art.21(2)(b) Incident Lifecycle Manager
Implements NIS2-compliant incident tracking with Art.23 threshold assessment.
"""
from dataclasses import dataclass, field
from datetime import datetime, timezone
from enum import Enum
from typing import Optional
import json
class IncidentSeverity(Enum):
P1_CRITICAL = "p1_critical" # Active threat, significant service impact
P2_HIGH = "p2_high" # Confirmed breach, limited containment
P3_MEDIUM = "p3_medium" # Potential breach, under investigation
P4_LOW = "p4_low" # Anomaly, likely benign
class IncidentPhase(Enum):
DETECTION = "detection"
ANALYSIS = "analysis"
CONTAINMENT = "containment"
ERADICATION = "eradication"
RECOVERY = "recovery"
POST_REVIEW = "post_incident_review"
CLOSED = "closed"
class IncidentType(Enum):
CREDENTIAL_COMPROMISE = "credential_compromise"
RANSOMWARE = "ransomware"
DATA_EXFILTRATION = "data_exfiltration"
SUPPLY_CHAIN = "supply_chain"
DDoS = "ddos"
INSIDER_THREAT = "insider_threat"
VULNERABILITY_EXPLOIT = "vulnerability_exploit"
OTHER = "other"
@dataclass
class TimelineEvent:
timestamp: str
phase: IncidentPhase
action: str
actor: str
evidence: Optional[str] = None
def to_dict(self) -> dict:
return {
"timestamp": self.timestamp,
"phase": self.phase.value,
"action": self.action,
"actor": self.actor,
"evidence": self.evidence,
}
@dataclass
class NIS2Incident:
incident_id: str
incident_type: IncidentType
severity: IncidentSeverity
affected_systems: list[str]
detection_source: str
detected_at: str = field(default_factory=lambda: datetime.now(timezone.utc).isoformat())
current_phase: IncidentPhase = IncidentPhase.DETECTION
timeline: list[TimelineEvent] = field(default_factory=list)
art23_threshold_met: Optional[bool] = None
art23_early_warning_sent: bool = False
gdpr_art33_applicable: bool = False
personal_data_affected: Optional[str] = None
affected_user_count: int = 0
service_impact_minutes: int = 0
responders: list[str] = field(default_factory=list)
closed_at: Optional[str] = None
def log_action(self, action: str, actor: str, evidence: Optional[str] = None):
"""Record a timestamped action in the incident timeline."""
event = TimelineEvent(
timestamp=datetime.now(timezone.utc).isoformat(),
phase=self.current_phase,
action=action,
actor=actor,
evidence=evidence,
)
self.timeline.append(event)
return event
def advance_phase(self, new_phase: IncidentPhase, actor: str):
"""Move to next IR lifecycle phase with audit trail."""
self.log_action(
f"Phase transition: {self.current_phase.value} → {new_phase.value}",
actor,
)
self.current_phase = new_phase
def assess_art23_threshold(self) -> dict:
"""
Assess whether NIS2 Art.23 'significant incident' threshold is met.
Significant incident indicators (per ENISA Technical Guideline 2023):
- Service unavailability >30 min affecting >5% active users
- Major impact on service delivery
- Other essential/important entities affected
"""
indicators = []
threshold_met = False
if self.service_impact_minutes > 30:
indicators.append(
f"Service unavailability: {self.service_impact_minutes} min (threshold: 30 min)"
)
threshold_met = True
if self.severity in (IncidentSeverity.P1_CRITICAL, IncidentSeverity.P2_HIGH):
if self.incident_type in (
IncidentType.RANSOMWARE,
IncidentType.DATA_EXFILTRATION,
IncidentType.SUPPLY_CHAIN,
):
indicators.append(
f"High-severity {self.incident_type.value} incident — likely major service impact"
)
threshold_met = True
if self.affected_user_count > 0:
# Conservative: flag if any significant user count affected
indicators.append(f"{self.affected_user_count} users affected")
if self.affected_user_count > 100:
threshold_met = True
self.art23_threshold_met = threshold_met
result = {
"threshold_met": threshold_met,
"indicators": indicators,
"action_required": (
"Prepare NIS2 Art.23 Early Warning (24h deadline from first knowledge)"
if threshold_met
else "Monitor — reassess if impact grows"
),
"gdpr_art33_check": (
"GDPR Art.33 parallel notification may apply — assess personal data exposure"
if self.gdpr_art33_applicable
else "GDPR Art.33 not triggered based on current assessment"
),
}
self.log_action(
f"Art.23 threshold assessment: {'THRESHOLD MET' if threshold_met else 'below threshold'}",
actor="NIS2IncidentHandler",
evidence=json.dumps(result),
)
return result
def generate_art23_early_warning(self) -> dict:
"""Generate structured data for NIS2 Art.23 24-hour Early Warning to NCA/CSIRT."""
if not self.art23_threshold_met:
raise ValueError(
"Art.23 threshold not confirmed. Run assess_art23_threshold() first."
)
return {
"notification_type": "NIS2_Art23_Early_Warning",
"incident_id": self.incident_id,
"detection_timestamp": self.detected_at,
"notification_deadline": self._compute_art23_deadline(hours=24),
"entity_type": "essential_or_important", # Populate for your entity
"incident_type": self.incident_type.value,
"initial_assessment": {
"affected_systems": self.affected_systems,
"affected_users": self.affected_user_count,
"service_impact_minutes": self.service_impact_minutes,
"suspected_cause": "under investigation", # Update from analysis
"cross_border_impact": False, # Update if applicable
},
"note": (
"Early Warning must be followed by detailed notification within 72 hours "
"and final report within 1 month per NIS2 Art.23(4)"
),
}
def _compute_art23_deadline(self, hours: int) -> str:
from datetime import timedelta
detected = datetime.fromisoformat(self.detected_at)
deadline = detected + timedelta(hours=hours)
return deadline.isoformat()
def to_pir_summary(self) -> dict:
"""Generate post-incident review summary for Art.21(2)(b) compliance records."""
if self.current_phase != IncidentPhase.CLOSED:
raise ValueError("Incident must be closed before generating PIR.")
detection_event = next(
(e for e in self.timeline if e.phase == IncidentPhase.DETECTION), None
)
containment_event = next(
(e for e in self.timeline if e.phase == IncidentPhase.CONTAINMENT), None
)
return {
"incident_id": self.incident_id,
"type": self.incident_type.value,
"severity": self.severity.value,
"timeline_events": len(self.timeline),
"responders": self.responders,
"art23_notification_required": self.art23_threshold_met,
"art23_early_warning_sent": self.art23_early_warning_sent,
"gdpr_art33_applicable": self.gdpr_art33_applicable,
"total_service_impact_minutes": self.service_impact_minutes,
"affected_user_count": self.affected_user_count,
"detection_to_containment": self._phase_duration(
IncidentPhase.DETECTION, IncidentPhase.CONTAINMENT
),
}
def _phase_duration(self, start_phase: IncidentPhase, end_phase: IncidentPhase) -> Optional[str]:
start = next((e for e in self.timeline if e.phase == start_phase), None)
end = next((e for e in self.timeline if e.phase == end_phase), None)
if start and end:
delta = datetime.fromisoformat(end.timestamp) - datetime.fromisoformat(start.timestamp)
total_minutes = int(delta.total_seconds() / 60)
return f"{total_minutes} minutes"
return None
# Example: credential compromise incident
if __name__ == "__main__":
incident = NIS2Incident(
incident_id="INC-2026-0047",
incident_type=IncidentType.CREDENTIAL_COMPROMISE,
severity=IncidentSeverity.P2_HIGH,
affected_systems=["aws-iam-admin-role", "production-database"],
detection_source="SIEM Rule: Impossible Travel Login",
affected_user_count=0, # internal admin account
service_impact_minutes=0, # no service disruption yet
gdpr_art33_applicable=False,
responders=["alice@example.com", "bob@example.com"],
)
# Detection phase
incident.log_action(
"SIEM alert: impossible travel — admin account accessed from DE and US within 45 min",
actor="siem-automation",
evidence="alert_id=SIEM-8847, source_ips=[91.234.x.x, 52.12.x.x]",
)
# Analysis
incident.advance_phase(IncidentPhase.ANALYSIS, actor="alice@example.com")
incident.log_action(
"Confirmed: admin session in AWS from 52.12.x.x accessed IAM, created new access key",
actor="alice@example.com",
evidence="cloudtrail_event_id=ct-7f29a, new_access_key=AKIA...",
)
# Update impact assessment
incident.service_impact_minutes = 0 # No service disruption
art23 = incident.assess_art23_threshold()
print("Art.23 Assessment:", json.dumps(art23, indent=2))
# Containment
incident.advance_phase(IncidentPhase.CONTAINMENT, actor="bob@example.com")
incident.log_action(
"Suspended compromised admin account, revoked all active sessions and API keys",
actor="bob@example.com",
evidence="actions: iam:DisableUser, iam:DeleteAccessKey INC-2026-0047-ak01",
)
incident.log_action(
"Snapshot taken of CloudTrail logs covering incident window",
actor="bob@example.com",
)
print(f"\nIncident {incident.incident_id} — Phase: {incident.current_phase.value}")
print(f"Timeline events: {len(incident.timeline)}")
print(f"Art.23 threshold: {incident.art23_threshold_met}")
6. NCA Audit Evidence Requirements for Art.21(2)(b)
Documentation Evidence
- IR Policy: Written policy defining what constitutes an incident, IR team structure, escalation thresholds, and Art.23 assessment criteria. Management-approved, dated.
- Incident Classification Matrix: How events map to severity levels (P1–P4) and what response each level requires
- Playbooks: At minimum, playbooks for ransomware, data breach, and credential compromise. Reference which Art.21(2) measures they depend on.
- Contact Directory: IR team contacts, external forensics, legal counsel, and NCA/CSIRT contact details (pre-populated, not searched during an incident)
- Training Records: Evidence that IR team has practised the playbooks (tabletop exercises, drills)
- Post-Incident Reviews: PIRs for any significant incidents in the review period
Technical Evidence
- SIEM coverage report: Which systems send logs, log retention settings, detection rules active
- Incident register: Log of all incidents (or significant events) in the review period, even those resolved without Art.23 notification
- Detection-to-containment metrics: Average time from alert to containment — NCAs use this to assess IR effectiveness
- Art.23 assessment records: For each incident above P2: documented Art.23 threshold assessment, even if threshold was not met
Common NCA Audit Findings (Incident Handling)
| Finding | Severity | Typical Remediation Timeline |
|---|---|---|
| No written IR policy or playbooks | Critical | 60 days |
| IR policy exists but not management-approved or outdated | High | 30 days |
| No SIEM or centralised logging — detection is reactive | High | 90 days |
| No Art.23 threshold assessment process | High | 30 days |
| Incident register incomplete (only major incidents logged) | Medium | 60 days |
| Playbooks untested (no tabletop exercises in past 12 months) | Medium | 90 days |
| No out-of-band communication channel for IR team | Medium | 30 days |
| Detection-to-containment >24h for P1 incidents | High | 90 days |
7. Integration with Other NIS2 Art.21(2) Measures
Art.21(2)(b) does not operate in isolation. It is the operational spine connecting most other mandatory measures.
Art.21(2)(a) — Risk Analysis: The risk analysis required by Art.21(2)(a) defines which incident types are most likely and most damaging for your specific entity. This prioritises which playbooks to develop first and which detection rules are highest priority for your SIEM.
Art.21(2)(c) — Business Continuity: Ransomware and destructive incidents trigger both Art.21(2)(b) IR processes and Art.21(2)(c) business continuity/DR plans. The handoff between the IR team (who handles the security investigation) and the DR team (who handles service restoration) must be defined in both policies. Unclear handoffs are a common finding.
Art.21(2)(d) — Supply Chain Security: Supply chain compromises often present as anomalous behaviour from trusted service accounts or third-party integrations. Detection rules for Art.21(2)(b) should specifically cover third-party access patterns. When a supply chain incident is confirmed, the GDPR Art.28 + NIS2 Art.21(2)(d) guide covers dual notification obligations.
Art.21(2)(e) — Secure Development: SDL processes from Art.21(2)(e) generate security telemetry (SAST findings, dependency alerts, secret scanning) that feeds into Art.21(2)(b) detection. A vulnerability discovered in production via SAST is an event that may require incident handling if exploitation is suspected.
Art.21(2)(j) — MFA: Authentication telemetry is the primary source for credential compromise detection. Failed MFA events, impossible travel, and unusual login patterns must flow from your IdP into your SIEM and trigger Art.21(2)(b) investigation processes. See the NIS2 Art.21(2)(j) MFA guide for authentication logging requirements.
Art.23 — Incident Reporting: Art.21(2)(b) processes generate the data needed for Art.23 notifications. The 24h early warning must reference: incident type, affected systems, and initial impact assessment — all outputs of the detection and analysis phases. The NIS2 Art.23 Incident Reporting guide covers the external reporting process in detail.
8. 25-Item NIS2 Art.21(2)(b) Incident Handling Checklist
Policy and Governance (1–6)
- 1. Written IR policy formally approved by management, defining scope, severity levels, and review cadence
- 2. IR team roles and responsibilities documented (not just names — specific decision authority per role)
- 3. Incident classification matrix mapping event types to severity levels (P1–P4) and required response
- 4. NCA/CSIRT contact information pre-populated (including national CERT and sector-specific CSIRT if applicable)
- 5. Legal counsel contact established for incident legal privilege and regulatory notification decisions
- 6. IR policy reviewed and updated within the past 12 months
Detection Capability (7–12)
- 7. Centralised log management (SIEM or equivalent) with coverage across all production systems
- 8. Detection rules configured for: brute force, impossible travel, anomalous egress, privilege escalation
- 9. Alert triage process defined — who receives alerts, SLA for P1/P2 response
- 10. Out-of-hours on-call rotation established and tested
- 11. Threat intelligence feeds integrated (ENISA, CSIRT, sector ISAC)
- 12. User reporting channel: employees can report suspicious activity with clear instructions
Playbooks (13–17)
- 13. Ransomware / destructive malware playbook written, reviewed, and tested
- 14. Credential compromise / account takeover playbook written and tested
- 15. Data exfiltration / breach playbook with GDPR Art.33 parallel notification step
- 16. Supply chain compromise playbook (covers third-party service account anomalies)
- 17. DDoS / availability incident playbook referencing Art.21(2)(c) DR handoff
Art.23 Integration (18–20)
- 18. Art.23 threshold assessment checklist embedded in all P1/P2 playbooks
- 19. 24h early warning template pre-drafted and approved by legal
- 20. Incident register maintained for all P3+ events (regardless of Art.23 applicability)
Evidence and Recovery (21–23)
- 21. Forensic evidence preservation procedure: snapshot before remediation, chain of custody
- 22. Containment actions documented in real-time during incidents
- 23. Post-incident review (PIR) required for all P1 and P2 incidents; PIR template exists
Testing and Improvement (24–25)
- 24. Tabletop exercise or live IR drill conducted in the past 12 months
- 25. PIR findings tracked to closure; playbooks updated when gaps identified
9. Implementation Timeline for June 2026 NCA Audit Readiness
| Week | Action | Owner |
|---|---|---|
| Week 1 | Inventory current IR processes — what exists vs what is required | CISO |
| Week 1-2 | Write IR policy (scope, severity levels, escalation, review cadence). Management sign-off. | CISO / Legal |
| Week 2-3 | Define Art.23 threshold assessment criteria for your entity type and sector | Legal / Compliance |
| Week 3-4 | Develop P1 playbooks: ransomware + credential compromise. Test with tabletop. | Security team |
| Week 4-5 | Develop P2 playbooks: data breach (GDPR Art.33 integration) + supply chain. | Security team |
| Week 5-6 | Audit SIEM coverage: confirm all production systems logging, detection rules active. | SecOps |
| Week 6-7 | Configure Art.21(2)(b) detection rules (brute force, impossible travel, anomalous egress). | SecOps |
| Week 7-8 | Establish incident register; backfill with any recent events. | CISO |
| Week 8-10 | Conduct tabletop exercise using ransomware scenario. Generate PIR. | IR team |
| Week 10-11 | Compile audit evidence package (policy, playbooks, incident register, SIEM coverage, PIR). | GRC |
| Week 11-12 | Internal audit review against NCA audit checklist. Close remaining gaps. | Internal audit |
| Ongoing | Quarterly playbook review; PIR after every P1/P2 incident. | Security team |
Summary
NIS2 Art.21(2)(b) requires formal, documented, and tested incident handling capability — not just the ability to react when something goes wrong. Key takeaways:
- Art.21(2)(b) is internal IR; Art.23 is the external reporting obligation. Both must be in place, but they are distinct requirements.
- Detection capability is mandatory: passive or reactive incident discovery does not satisfy "policies and procedures regarding incident handling."
- The six-phase lifecycle (preparation, detection, analysis, containment, eradication, recovery + PIR) maps directly to what NCA auditors will assess.
- Art.23 threshold assessment must be embedded in every P1/P2 playbook — not added retrospectively.
- Audit evidence: IR policy, playbooks, incident register, SIEM coverage documentation, Art.23 assessment records for significant events, and at least one PIR.
See also:
- NIS2 Art.21(2)(c): Business Continuity, Backup and Disaster Recovery Guide
- NIS2 Art.23: 24h and 72h Incident Reporting to NCAs
- NIS2 + GDPR Dual Reporting: Simultaneous Incident Notification
- NIS2 Art.21(2)(e): Secure Development Lifecycle Guide
- NIS2 Art.21(2)(j): Multi-Factor Authentication Guide
- NIS2 Art.21 Complete Risk Management Framework