NIS2 Directive Technical Implementation: Incident Reporting, Supply Chain, and Vulnerability Management

NIS2 Directive Technical Implementation: Incident Reporting, Supply Chain, and Vulnerability Management

Problem

The NIS2 Directive (EU 2022/2555) became enforceable across EU member states from October 2024. It replaces NIS1, which applied primarily to operators of essential services in a narrow set of sectors. NIS2 substantially widens scope: it covers approximately 160,000 entities across 18 sectors, including cloud providers, managed service providers, DNS operators, digital infrastructure companies, and many manufacturing and food production businesses that were not previously regulated.

The regulation introduces specific technical obligations that fall directly on platform, infrastructure, and security teams rather than only on legal and compliance functions:

Incident reporting timelines are precise and short. Organizations must notify their national Computer Security Incident Response Team (CSIRT) or competent authority within 24 hours of becoming aware of a significant incident (early warning), provide a full incident notification within 72 hours (with cause assessment and initial impact), and submit a final report within one month. These timelines require automated incident detection and triage pipelines — a manual process cannot reliably produce a 24-hour notification for incidents discovered outside business hours.

Supply chain security is explicitly required under Article 21. Organizations must perform security assessments of their direct suppliers and consider the security posture of suppliers’ suppliers. The regulation does not define the exact methodology, but it does require documented due diligence, risk-based supplier selection, and ongoing monitoring. This means SBOMs, software composition analysis, and vendor security questionnaires that are currently best practices become compliance obligations.

Vulnerability handling requires organizations to maintain processes for discovering, assessing, and remediating vulnerabilities. For entities in scope of the critical infrastructure provisions, coordinated vulnerability disclosure (CVD) programs are increasingly expected. The regulation also creates obligations around encryption: Article 21 requires use of cryptography and encryption where appropriate for the protection of network and information systems.

Logging and monitoring requirements are implied by the incident detection obligation: you cannot report a significant incident within 24 hours if you are not monitoring for incidents. Specifically, NIS2 requires incident response capabilities, the ability to analyze incidents post-hoc, and business continuity arrangements.

The practical challenge for technical teams is that NIS2 defines obligations in terms of outcomes, not specific technical controls. This is intentional (technology-neutrality) but creates interpretation risk. Organizations are expected to implement “appropriate and proportionate technical and organisational measures” — a phrase that requires translating regulatory language into specific controls, then documenting how those controls satisfy the obligation.

This article maps each major NIS2 technical obligation to concrete controls with implementation guidance. It focuses on the engineering implementation, not legal interpretation. Organizations should obtain legal advice on whether and how NIS2 applies to their specific situation.

Target systems: Any EU-based or EU-serving technology organization in NIS2 scope; cloud infrastructure, managed service providers, DNS operators, software providers, and critical infrastructure operators; platform teams responsible for logging, monitoring, incident response, and supply chain security tooling.


Threat Model

The “threats” in a compliance context are regulatory and operational rather than adversarial:

Non-compliance risk — missed incident reporting. An incident is detected by a monitoring tool but the alert does not reach the team that must file the 24-hour notification. Either the escalation path is broken, the incident is mis-classified as below-threshold, or no on-call rotation covers the detection window. Result: missed deadline, supervisory authority notification, potential fine (up to €10M or 2% of global annual turnover for essential entities).

Non-compliance risk — unverified supply chain. A critical dependency (cloud provider, SaaS tool, third-party library) has a security incident that impacts the organization’s systems. Post-incident, the supervisory authority requests evidence of supplier risk assessment. No formal assessment exists for that supplier. Result: inability to demonstrate due diligence.

Operational risk — delayed vulnerability remediation. A critical vulnerability in a production system is disclosed publicly. Without an SLA-tracked vulnerability management process, the fix is delayed beyond what is proportionate. If the system is breached as a result, the absence of a managed remediation process is evidence of inadequate security measures.

Strategic risk — inadequate cryptography. Systems continue to use deprecated TLS versions, weak cipher suites, or unencrypted communication channels for data classified as sensitive. Post-incident forensics reveals this as a contributing factor. The lack of documented cryptography standards and enforcement is a NIS2 compliance finding.


Configuration / Implementation

Step 1 — Map NIS2 Article 21 obligations to control domains

NIS2 Article 21 requires minimum security measures across 10 areas. Map each to your control framework:

NIS2 Article 21 Area Concrete Technical Controls
Risk analysis and IS policies Threat model documentation; asset inventory with classification
Incident handling SIEM/alerting pipeline; incident runbooks; on-call rotation
Business continuity and crisis management Backup automation; RTO/RPO SLAs; DR runbooks
Supply chain security SBOM generation; SCA in CI/CD; vendor questionnaire process
Network and IS security (procurement) Security requirements in procurement process; baseline hardening standards
Vulnerability handling Vulnerability scanning; patching SLAs; CVD process
Policies for cryptography Cryptographic standards document; TLS configuration enforcement
Human resources security Security training records; background check policy
Access control MFA enforcement; privileged access management; access reviews
Multi-factor authentication MFA coverage metric; exceptions process

Step 2 — Build the 24-hour incident notification pipeline

The 24-hour early warning is the hardest timeline to meet operationally. It requires:

  1. Detection firing within minutes of incident onset.
  2. Alert reaching an on-call engineer within 15 minutes.
  3. Initial triage completed within 2 hours.
  4. Determination of “significant incident” threshold within 4 hours.
  5. Draft notification sent to CSIRT within 24 hours.

Automate the detection-to-notification pipeline:

# Example: Alertmanager routing for NIS2 significant-incident triage
# /etc/alertmanager/alertmanager.yml

route:
  receiver: default
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  routes:
  # Critical security alerts route to NIS2 triage channel
  - match_re:
      severity: "critical|security"
    receiver: nis2-triage
    group_wait: 10s
    repeat_interval: 1h
    continue: true

receivers:
- name: nis2-triage
  pagerduty_configs:
  - service_key: ${PAGERDUTY_NIS2_KEY}
    severity: critical
    description: |
      POTENTIAL NIS2 REPORTABLE INCIDENT
      Determine within 4 hours whether this meets the significant incident threshold.
      If yes, initial notification to CSIRT required within 24 hours of detection.
      Runbook: https://runbooks.internal/nis2-incident-response
  slack_configs:
  - channel: '#nis2-incidents'
    send_resolved: true
    title: '[NIS2-TRIAGE] {{ .GroupLabels.alertname }}'
    text: |
      *Detection Time:* {{ .StartsAt }}
      *24h Notification Deadline:* {{ .StartsAt | add "24h" }}
      *72h Full Report Deadline:* {{ .StartsAt | add "72h" }}
      *Classification Required By:* {{ .StartsAt | add "4h" }}

Create an incident classification runbook aligned with NIS2’s “significant incident” definition:

# NIS2 Incident Classification Runbook

## Significant Incident Threshold (EU 2022/2555 Art. 23)

A significant incident is one that:
1. Has caused or is capable of causing severe operational disruption to the services or financial losses, OR
2. Has affected or is capable of affecting other natural or legal persons by causing considerable material or non-material damage.

## Classification Decision Tree

**Step 1: Is this a security incident?**
- Confirmed: unauthorized access, data exfiltration, ransomware, DDoS affecting availability → proceed to Step 2
- Suspected: proceed to Step 2 with lower confidence threshold

**Step 2: Does it meet significance threshold?**
- Service availability reduced >20% for >30 minutes for critical services → SIGNIFICANT
- Customer data potentially accessed or exfiltrated → SIGNIFICANT  
- Financial systems affected → SIGNIFICANT
- Internal-only disruption with no customer/service impact → NOT SIGNIFICANT (document reasoning)

**Step 3: If SIGNIFICANT:**
- Time-stamp this decision: T0
- File early warning to [CSIRT contact] by T0 + 24h
- File full notification by T0 + 72h
- File final report by T0 + 30 days

Step 3 — Implement supply chain security controls

NIS2 Article 21(3) requires supply chain risk management. Implement three layers:

Layer 1 — SBOM generation for all software you deploy:

# GitHub Actions: generate SBOM for every build
- name: Generate SBOM
  uses: anchore/sbom-action@v0
  with:
    image: ${{ env.IMAGE_NAME }}
    format: spdx-json
    output-file: sbom.spdx.json

- name: Upload SBOM to artifact store
  uses: actions/upload-artifact@v4
  with:
    name: sbom-${{ github.sha }}
    path: sbom.spdx.json
    retention-days: 365  # Retain for NIS2 audit purposes

Layer 2 — Software Composition Analysis (SCA) blocking on critical CVEs:

# In CI/CD pipeline
- name: SCA scan with CVSS threshold
  run: |
    grype sbom:./sbom.spdx.json \
      --fail-on-severity high \
      --output table \
      --config .grype.yml

# .grype.yml
ignore:
  # Document exceptions with justification (required for NIS2 audit trail)
  - vulnerability: CVE-2023-XXXXX
    reason: "Mitigated by network segmentation; patch pending vendor release"
    expires: "2026-07-01"

Layer 3 — Vendor security questionnaire and annual review:

Create a lightweight vendor assessment process using a standardized questionnaire aligned with NIS2 requirements:

# Vendor Security Assessment Questionnaire (NIS2-aligned)

Vendor: [Name]  
Assessment Date: [Date]  
Assessor: [Name]  
Next Review: [Date + 12 months]

## Incident Response (NIS2 Art. 21(2)(b))
1. Do you have a documented incident response process? [Y/N + evidence]
2. What is your SLA for notifying customers of security incidents? [Hours]
3. Have you had any security incidents affecting our data in the past 12 months? [Y/N + details]

## Supply Chain Security (NIS2 Art. 21(3))
4. Do you conduct security assessments of your own subprocessors? [Y/N]
5. Do you generate SBOMs for software you deliver? [Y/N]
6. What is your vulnerability disclosure process? [Description]

## Access Control (NIS2 Art. 21(2)(i))
7. Is MFA enforced for all administrative access? [Y/N]
8. Do you conduct access reviews at minimum annually? [Y/N]

## Cryptography (NIS2 Art. 21(2)(h))
9. Is data encrypted in transit using TLS 1.2 minimum? [Y/N]
10. Is sensitive data encrypted at rest? [Y/N + algorithm]

Step 4 — Implement vulnerability management with NIS2-aligned SLAs

# Vulnerability SLA policy — document and enforce in your scanner/ticketing system

vulnerability_sla:
  critical:  # CVSS 9.0–10.0
    patch_sla_days: 7
    exception_approval: CISO
    nis2_rationale: "Immediate threat to service integrity"
  
  high:      # CVSS 7.0–8.9
    patch_sla_days: 30
    exception_approval: Security Team Lead
    nis2_rationale: "Significant risk requiring prompt remediation"
  
  medium:    # CVSS 4.0–6.9
    patch_sla_days: 90
    exception_approval: Engineering Manager
    nis2_rationale: "Risk accepted with compensating controls"
  
  low:       # CVSS 0.1–3.9
    patch_sla_days: 180
    exception_approval: Self-documented
    nis2_rationale: "Low risk; scheduled maintenance window"

Track SLA adherence as a metric:

# Example: generate monthly SLA compliance report
# Query your vulnerability scanner API (Trivy, Grype, Snyk) for overdue findings

# Using Grype output:
grype db check
grype image:your-app:latest --output json | \
  jq '[.matches[] | 
    select(.vulnerability.severity | test("Critical|High")) | 
    {
      id: .vulnerability.id,
      severity: .vulnerability.severity,
      package: .artifact.name,
      published: .vulnerability.publishedDate,
      days_since_publish: (now - (.vulnerability.publishedDate | fromdateiso8601) | /86400 | round)
    }
  ] | sort_by(.days_since_publish) | reverse'

Step 5 — Enforce cryptographic standards

Document and enforce minimum cryptographic standards across your systems:

# /etc/nginx/conf.d/tls-policy.conf
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;

# HSTS with 1-year max-age
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

Audit TLS configuration across your fleet:

# Scan all HTTPS endpoints for weak TLS
testssl.sh --csvfile tls-audit-$(date +%Y%m).csv \
           --severity HIGH \
           --warnings batch \
           --quiet \
           https://your-service.example.com

# Or use tlsx for fleet scanning
tlsx -list endpoints.txt -port 443,8443 \
     -tls-version -cipher \
     -json -o tls-inventory-$(date +%Y%m).json

Step 6 — Maintain audit trails for NIS2 evidence

NIS2 requires organizations to demonstrate compliance to supervisory authorities. Implement evidence retention:

# Retain security logs for minimum 12 months (NIS2 doesn't specify; many CSIRTs recommend 24+ months)
# Example: S3 lifecycle policy for CloudWatch Logs export

aws s3api put-bucket-lifecycle-configuration \
  --bucket security-audit-logs-${ACCOUNT_ID} \
  --lifecycle-configuration file://lifecycle.json

# lifecycle.json
{
  "Rules": [{
    "ID": "NIS2-24-month-retention",
    "Status": "Enabled",
    "Filter": {"Prefix": "security-logs/"},
    "Transitions": [
      {"Days": 90, "StorageClass": "STANDARD_IA"},
      {"Days": 365, "StorageClass": "GLACIER"}
    ],
    "Expiration": {"Days": 730}
  }]
}

Build a NIS2 compliance evidence register:

# NIS2 Evidence Register (update quarterly)

| Control Area | Control | Evidence Location | Last Reviewed | Next Review |
|---|---|---|---|---|
| Incident handling | 24h notification runbook | /runbooks/nis2-incident-response.md | 2026-02-01 | 2026-08-01 |
| Supply chain | SBOM generation in CI/CD | GitHub Actions workflow log | 2026-03-15 | 2026-09-15 |
| Vulnerability management | SLA policy document | /policies/vulnerability-management.md | 2026-01-10 | 2026-07-10 |
| Cryptography | TLS audit report | s3://audit-bucket/tls-audit-202604.csv | 2026-04-01 | 2026-10-01 |
| Access control | MFA coverage report | IAM reporting dashboard | 2026-05-01 | 2026-11-01 |

Expected Behaviour

Obligation Without controls With controls
24-hour incident notification Manual process; high miss risk outside business hours Automated alert → PagerDuty → runbook; T+24h deadline tracked automatically
Supply chain SBOM No inventory of third-party components SBOM generated on every build; retained for 12 months; SCA blocks critical CVEs
Vulnerability SLA Ad-hoc patching; no tracked SLA SLA defined per severity; breaches create escalation tickets automatically
TLS audit Unknown cipher and protocol state across services Monthly automated scan; report retained; findings linked to remediation tickets
NIS2 evidence register No centralized evidence; audit prep is 2-week scramble Evidence register updated quarterly; evidence location documented; retrieval < 1 hour

Trade-offs

Aspect Benefit Cost Mitigation
7-day critical patch SLA Meets NIS2 proportionality expectations; reduces window Forces emergency changes; may conflict with change freeze periods Define exception process with compensating controls (WAF rule, network segmentation); document for auditor
24-month log retention Provides forensic evidence for NIS2 final reports Storage cost; GDPR tension (retain only as long as necessary) Apply data minimization to logs (no raw payload; only metadata); use cold storage tiers
SBOM for every build Complete supply chain inventory; NIS2 evidence CI/CD pipeline duration increases by 30–90 seconds Use parallel SBOM generation step; cache SBOM for identical base images
Vendor questionnaire annual cycle Documents due diligence Time-intensive for large vendor list Tier vendors by risk level; full questionnaire only for critical suppliers; use standardized responses (CSA CAIQ, shared assessments)

Failure Modes

Failure Symptom Detection Recovery
On-call engineer misclassifies incident as non-significant No 24h notification filed; becomes compliance finding when incident is re-classified later Post-incident review; CSIRT may contact organization proactively Retrain classification process; update runbook decision tree; consider voluntary late notification to CSIRT (better than silence)
SBOM generation fails silently in CI Build succeeds; no SBOM artifact uploaded; compliance gap accumulates Missing artifact in retention store; weekly SBOM audit job finds gaps Add SBOM presence check as a required CI step; fail build if SBOM artifact is absent
Vendor fails to respond to annual security questionnaire Gap in supply chain evidence Annual review process shows outstanding questionnaire Escalate to vendor account manager; document attempts; consider risk-based offboarding if critical vendor unresponsive for 90 days
TLS scan finds deprecated protocol on internal service Internal service using TLS 1.0; low visibility because it’s “internal only” Fleet scan report; NIS2 applies to internal as well as external systems Update service TLS config; prioritize by data classification of traffic carried