2026-04-17·16 min read·

DORA Art.5–9: ICT Risk Management Framework — Governance, Identification, and Protection for Financial Services (2026)

Post #403 in the sota.io EU Cyber Compliance Series

The EU Digital Operational Resilience Act (DORA, Regulation 2022/2554) has applied to approximately 22,000 EU financial entities since 17 January 2025. At its core, DORA Chapter II (Articles 5–16) mandates a comprehensive ICT risk management framework — not as a one-time compliance exercise but as a living, board-owned governance structure.

Articles 5 through 9 form the foundation layer of that framework:

This guide walks through each article, explains what is actually required versus what guidance documents merely recommend, provides a Python implementation for self-assessment, and maps the DORA requirements to NIS2 Art.21 for dual-regulated entities.


1. Who Is Subject to DORA Art.5–9

DORA Art.2(1) defines the entities in scope. The core financial categories include:

Credit and payment institutions:

Investment and insurance:

Capital markets and infrastructure:

Digital assets and data:

ICT third-party providers:

Microenterprise exemption (Art.16): Entities with fewer than 10 employees and annual turnover/balance sheet ≤ €2M may apply a simplified ICT risk management framework under Art.16. They are still subject to Art.5–9 but with reduced documentary requirements and proportional governance structures.

Even if your organisation is not directly subject to DORA (e.g., you are an EU cloud provider or SaaS vendor), your financial sector customers will contractually push DORA Art.30 requirements downstream: incident reporting SLAs, audit rights, exit assistance, and documentation of your own ICT risk controls.


2. Art.5: Governance — The Management Body's Role

DORA Art.5 places ultimate accountability for ICT risk at the management body level — not the CISO, not the CTO, but the board of directors or equivalent governing body.

Art.5(1): Board Accountability

The management body of a financial entity defines, approves, oversees, and is responsible for the implementation of all arrangements related to the ICT risk management framework.

This creates a three-part duty chain that mirrors NIS2 Art.20:

  1. Define: The board sets the ICT risk appetite and strategic objectives
  2. Approve: The board formally approves the ICT risk management framework document
  3. Oversee: The board monitors implementation through regular reporting

Critically, DORA does not allow the board to delegate accountability — only operational responsibility. The board remains answerable to the competent authority (ECB, national NCA) for ICT risk failures.

Art.5(2): ICT Risk Tolerance

The management body must define and document the financial entity's tolerance level for ICT risk. This translates operationally into:

ICT Risk DimensionTolerance Example
Maximum acceptable system downtimeRTO ≤ 4h for core banking systems
Maximum data loss windowRPO ≤ 15 minutes for payment ledgers
Acceptable number of major ICT incidents per year≤ 2 incidents triggering Art.19 reporting
Third-party concentration risk thresholdNo single vendor > 40% of critical infrastructure

These tolerance thresholds feed directly into Art.11 (business continuity) and Art.19 (incident reporting) design decisions.

Art.5(3): Framework Approval

The management body approves the ICT risk management framework and is responsible for its implementation. This approval must be documented (board minutes or equivalent) and the framework must be reviewed at least annually.

Art.5(4): Board Member ICT Responsibility

At least one member of the management body must be specifically responsible for ICT risk oversight. For large institutions, this may be a dedicated board-level CTO/CISO role or a board risk committee chairperson with explicit ICT mandate.

Art.5(6): Dedicated ICT Risk Function

Financial entities (except microenterprises) must establish a dedicated ICT risk management function. The function must be independent of business lines that generate ICT risk exposure — the same independence principle that governs operational risk functions under CRR/CRD.

The ICT risk management function typically covers:


3. Art.6: ICT Risk Management Framework Structure

Art.6 defines what the ICT risk management framework must contain. It is not sufficient to have a policy document that claims coverage — the framework must demonstrably implement each required element.

Art.6(1): Framework Requirements

The ICT risk management framework must be comprehensive, documented, and regularly reviewed. It must:

Art.6(2): Required Framework Elements

The framework must cover the full ICT risk lifecycle across six mandatory domains:

DomainDORA ReferenceRequired Capabilities
IdentificationArt.8Asset inventory, dependency mapping, vulnerability identification
ProtectionArt.9Network segmentation, access control, patch management, encryption
DetectionArt.10Monitoring, anomaly detection, logging
ResponseArt.11, 17Incident classification, escalation, communication
RecoveryArt.11, 12RTO/RPO achievement, backup restoration, DR testing
CommunicationArt.14, 19Internal escalation, regulatory reporting, stakeholder communication

Art.6(3): ICT Third-Party Risk Coverage

The framework must explicitly cover ICT third-party risk — not just internal ICT risk. This means:

Art.6(4): Annual Review and Documentation

The framework documentation must be updated following:

Art.6(8): Budget and Digital Transformation Reporting

The management body must receive an annual report covering:

This requirement creates a formal board-level feedback loop that connects operational ICT risk data to strategic governance decisions.


4. Art.7: ICT Systems, Protocols, and Tools

Art.7 sets baseline quality requirements for the ICT infrastructure underpinning financial operations. The requirements are outcome-based rather than prescriptive — the competent authority assesses whether the deployed infrastructure is fit for purpose.

Core Requirements

Reliability and resilience (Art.7(a)): Systems must be appropriate in terms of quantity and quality, technologically resilient, reliable, and sufficiently capable of ensuring operational continuity.

Performance capacity (Art.7(b)): ICT systems must have sufficient capacity and performance to handle transaction volumes including peak loads. This implies:

Technological currency (Art.7(c)): ICT systems must be kept up-to-date. End-of-life (EoL) or end-of-support (EoS) software in production is a direct compliance risk under Art.7 — not merely a security risk.

Physical and logical redundancy: Critical ICT systems must have redundancy arrangements proportionate to the business functions they support. Single points of failure in critical payment paths are a primary supervisory concern.

Practical Implications for Cloud Infrastructure

Art.7 effectively requires that cloud infrastructure for financial entities meets the same standards as on-premises infrastructure:

EU-hosted infrastructure (deployed within EU data centres with EU-only data paths) reduces the jurisdictional exposure associated with cloud systems subject to non-EU data access laws — a consideration explicitly acknowledged in DORA Recital 64 regarding ICT third-party risk and data sovereignty.


5. Art.8: Identification — Asset Inventory and Vulnerability Management

Art.8 establishes the identification domain of the ICT risk management framework. It is a prerequisite for everything else: you cannot protect, detect, or recover what you have not identified.

Art.8(1): ICT Asset Identification and Classification

Financial entities must identify, classify, and document all ICT assets that support business functions. The classification should reflect:

A practical taxonomy:

Asset TierDefinitionExamples
Tier 1 — CriticalDirect support of CIFs; regulatory reportingCore banking, payment processing, trade matching
Tier 2 — ImportantSupports Tier 1; significant customer impactCRM, document management, identity systems
Tier 3 — StandardInternal tools; no direct regulatory impactHR systems, internal collaboration tools
Tier 4 — Non-productionDev/test/staging environmentsDevelopment clusters, sandboxes

Art.8(2): Configuration Register

Beyond identifying assets, DORA requires a configuration register — documenting the interdependencies between ICT assets. This maps:

The configuration register is the foundation for both Art.9 protection controls and Art.11 business continuity planning.

Art.8(3): Dependency Mapping

Financial entities must map how ICT assets support business functions — specifically critical or important functions (CIFs) as defined in Art.3(22). This business function → ICT asset dependency map must be:

Art.8(4): Vulnerability Identification

Art.8(4) requires financial entities to identify and document ICT-related vulnerabilities on an ongoing basis. This encompasses:


6. Art.9: Protection and Prevention

Art.9 defines the protection domain — the controls that prevent ICT risks from materialising into incidents. The article covers four distinct control areas.

Art.9(1): Information Security Policies

Financial entities must have documented information security policies covering:

The DORA requirement for MFA at critical system access is absolute — not aspirational. Competent authorities have cited MFA gaps in supervisory review findings across multiple jurisdictions.

Art.9(2): Change Management and Patch Management

Change management requirements:

Patch management requirements:

A defensible patch SLA framework aligned with DORA and common NCA expectations:

SeverityCVSS ScorePatch SLA
Critical9.0–10.024–72 hours
High7.0–8.97 calendar days
Medium4.0–6.930 calendar days
Low0.1–3.990 calendar days

Art.9(3): Data Security

DORA requires controls covering the full data lifecycle:

Art.9(4): Physical and Environmental Controls

ICT systems must be protected against physical threats:


7. Python DORAICTRiskChecker Implementation

The following Python implementation provides a structured self-assessment tool for DORA Art.5–9 compliance. It models the key requirements as checkable conditions and produces a weighted compliance score.

from dataclasses import dataclass, field
from enum import Enum
from typing import Optional
import json
from datetime import date, timedelta


class AssetTier(Enum):
    CRITICAL = 1
    IMPORTANT = 2
    STANDARD = 3
    NON_PRODUCTION = 4


class PatchSeverity(Enum):
    CRITICAL = "critical"
    HIGH = "high"
    MEDIUM = "medium"
    LOW = "low"


PATCH_SLA_DAYS = {
    PatchSeverity.CRITICAL: 3,
    PatchSeverity.HIGH: 7,
    PatchSeverity.MEDIUM: 30,
    PatchSeverity.LOW: 90,
}


@dataclass
class ICTAsset:
    name: str
    tier: AssetTier
    has_config_entry: bool
    business_function_mapped: bool
    last_vulnerability_scan: Optional[date]
    eol_date: Optional[date] = None
    mfa_enforced: bool = False
    encrypted_at_rest: bool = False


@dataclass
class GovernanceStatus:
    board_ict_risk_owner_defined: bool
    framework_last_approved: Optional[date]
    ict_risk_function_exists: bool
    ict_risk_tolerance_documented: bool
    annual_board_report_issued: bool


@dataclass
class PatchItem:
    cve_id: str
    severity: PatchSeverity
    identified_date: date
    patched_date: Optional[date]
    compensating_control: bool = False


@dataclass
class DORAICTRiskFindings:
    art5_governance_score: float
    art6_framework_score: float
    art7_systems_score: float
    art8_identification_score: float
    art9_protection_score: float
    overall_score: float
    critical_gaps: list[str]
    recommendations: list[str]


class DORAICTRiskChecker:
    """
    Self-assessment tool for DORA Art.5-9 ICT risk management framework.
    Weights reflect supervisory emphasis: governance (25%) + identification (25%)
    + protection (25%) + systems (15%) + framework (10%).
    """

    def __init__(
        self,
        governance: GovernanceStatus,
        assets: list[ICTAsset],
        patches: list[PatchItem],
        has_third_party_register: bool,
        has_network_segmentation: bool,
        change_management_documented: bool,
        data_classification_exists: bool,
    ):
        self.governance = governance
        self.assets = assets
        self.patches = patches
        self.has_third_party_register = has_third_party_register
        self.has_network_segmentation = has_network_segmentation
        self.change_management_documented = change_management_documented
        self.data_classification_exists = data_classification_exists

    def check_art5_governance(self) -> tuple[float, list[str]]:
        gaps = []
        score = 0.0

        if self.governance.board_ict_risk_owner_defined:
            score += 0.25
        else:
            gaps.append("Art.5(4): No board member designated for ICT risk oversight")

        if self.governance.framework_last_approved:
            days_since = (date.today() - self.governance.framework_last_approved).days
            if days_since <= 365:
                score += 0.25
            else:
                gaps.append(
                    f"Art.5(3): Framework not reviewed in {days_since} days (>365 day threshold)"
                )
        else:
            gaps.append("Art.5(3): ICT risk management framework not formally approved by board")

        if self.governance.ict_risk_function_exists:
            score += 0.20
        else:
            gaps.append("Art.5(6): No dedicated ICT risk management function established")

        if self.governance.ict_risk_tolerance_documented:
            score += 0.15
        else:
            gaps.append("Art.5(2): ICT risk tolerance not documented")

        if self.governance.annual_board_report_issued:
            score += 0.15
        else:
            gaps.append("Art.6(8): Annual board ICT risk report not issued")

        return score, gaps

    def check_art8_identification(self) -> tuple[float, list[str]]:
        gaps = []
        score = 0.0
        critical_assets = [a for a in self.assets if a.tier == AssetTier.CRITICAL]

        if not self.assets:
            gaps.append("Art.8(1): No ICT asset inventory found")
            return 0.0, gaps

        # Asset classification coverage
        classified_pct = len([a for a in self.assets if a.tier is not None]) / len(self.assets)
        score += classified_pct * 0.25

        # Configuration register coverage
        config_pct = len([a for a in self.assets if a.has_config_entry]) / len(self.assets)
        if config_pct < 1.0:
            gaps.append(
                f"Art.8(2): {int((1 - config_pct) * 100)}% of assets lack configuration register entries"
            )
        score += config_pct * 0.25

        # Business function mapping for critical assets
        if critical_assets:
            mapped_pct = len([a for a in critical_assets if a.business_function_mapped]) / len(
                critical_assets
            )
            if mapped_pct < 1.0:
                gaps.append(
                    f"Art.8(3): {int((1 - mapped_pct) * 100)}% of critical assets not mapped to business functions"
                )
            score += mapped_pct * 0.25

        # Vulnerability scan freshness (Tier 1/2: monthly; Tier 3: quarterly)
        scan_compliant = 0
        for asset in self.assets:
            if asset.last_vulnerability_scan:
                days_stale = (date.today() - asset.last_vulnerability_scan).days
                threshold = 30 if asset.tier in (AssetTier.CRITICAL, AssetTier.IMPORTANT) else 90
                if days_stale <= threshold:
                    scan_compliant += 1
            if asset.eol_date and asset.eol_date <= date.today():
                gaps.append(f"Art.7(c): {asset.name} is End-of-Life — immediate remediation required")

        scan_pct = scan_compliant / len(self.assets) if self.assets else 0
        score += scan_pct * 0.25

        return score, gaps

    def check_art9_protection(self) -> tuple[float, list[str]]:
        gaps = []
        score = 0.0

        # MFA for critical/important systems
        mfa_required = [
            a for a in self.assets if a.tier in (AssetTier.CRITICAL, AssetTier.IMPORTANT)
        ]
        if mfa_required:
            mfa_pct = len([a for a in mfa_required if a.mfa_enforced]) / len(mfa_required)
            if mfa_pct < 1.0:
                gaps.append(
                    f"Art.9(1): MFA not enforced on {int((1 - mfa_pct) * 100)}% of critical/important systems"
                )
            score += mfa_pct * 0.20

        # Encryption at rest for critical systems
        encrypt_required = [a for a in self.assets if a.tier == AssetTier.CRITICAL]
        if encrypt_required:
            encrypt_pct = len([a for a in encrypt_required if a.encrypted_at_rest]) / len(
                encrypt_required
            )
            if encrypt_pct < 1.0:
                gaps.append(
                    f"Art.9(3): {int((1 - encrypt_pct) * 100)}% of critical assets lack encryption at rest"
                )
            score += encrypt_pct * 0.20

        # Network segmentation
        if self.has_network_segmentation:
            score += 0.20
        else:
            gaps.append("Art.9(1): Network segmentation for critical systems not documented")

        # Patch compliance
        today = date.today()
        overdue_patches = []
        for patch in self.patches:
            if patch.patched_date:
                continue  # Patched — compliant
            if patch.compensating_control:
                continue  # Compensating control documented — acceptable
            sla_days = PATCH_SLA_DAYS[patch.severity]
            days_open = (today - patch.identified_date).days
            if days_open > sla_days:
                overdue_patches.append(
                    f"{patch.cve_id} ({patch.severity.value}): {days_open}d open (SLA: {sla_days}d)"
                )

        if overdue_patches:
            gaps.append(f"Art.9(2): {len(overdue_patches)} patches overdue SLA: {', '.join(overdue_patches[:3])}")
            score += max(0, 0.20 * (1 - len(overdue_patches) / max(len(self.patches), 1)))
        else:
            score += 0.20

        # Change management
        if self.change_management_documented:
            score += 0.10
        else:
            gaps.append("Art.9(2): Change management process not documented")

        # Data classification
        if self.data_classification_exists:
            score += 0.10
        else:
            gaps.append("Art.9(3): Data classification scheme not established")

        return score, gaps

    def run(self) -> DORAICTRiskFindings:
        art5_score, art5_gaps = self.check_art5_governance()
        art8_score, art8_gaps = self.check_art8_identification()
        art9_score, art9_gaps = self.check_art9_protection()

        # Art.6 framework score (based on coverage of required elements)
        art6_elements = [
            self.has_third_party_register,
            self.governance.framework_last_approved is not None,
            len(self.assets) > 0,
        ]
        art6_score = sum(art6_elements) / len(art6_elements)
        art6_gaps = []
        if not self.has_third_party_register:
            art6_gaps.append("Art.6(3): ICT third-party risk not covered by framework (no vendor register)")

        # Art.7 systems score (EoL software check + basic capacity assumption)
        eol_assets = [a for a in self.assets if a.eol_date and a.eol_date <= date.today()]
        art7_score = max(0, 1.0 - (len(eol_assets) / max(len(self.assets), 1)))
        art7_gaps = []

        all_gaps = art5_gaps + art6_gaps + art7_gaps + art8_gaps + art9_gaps

        overall = (
            art5_score * 0.25
            + art6_score * 0.10
            + art7_score * 0.15
            + art8_score * 0.25
            + art9_score * 0.25
        )

        recommendations = []
        if art5_score < 0.8:
            recommendations.append(
                "Priority 1: Formalise board ICT risk governance (Art.5 board resolution + ICT risk function charter)"
            )
        if art8_score < 0.8:
            recommendations.append(
                "Priority 2: Complete ICT asset inventory with configuration register and business function mapping (Art.8)"
            )
        if art9_score < 0.8:
            recommendations.append(
                "Priority 3: Enforce MFA on all critical systems and resolve overdue patches (Art.9)"
            )
        if not self.has_third_party_register:
            recommendations.append(
                "Priority 4: Implement ICT third-party register covering all critical vendors (Art.6(3) + Art.28)"
            )

        return DORAICTRiskFindings(
            art5_governance_score=round(art5_score, 2),
            art6_framework_score=round(art6_score, 2),
            art7_systems_score=round(art7_score, 2),
            art8_identification_score=round(art8_score, 2),
            art9_protection_score=round(art9_score, 2),
            overall_score=round(overall, 2),
            critical_gaps=all_gaps,
            recommendations=recommendations,
        )

Example Usage

governance = GovernanceStatus(
    board_ict_risk_owner_defined=True,
    framework_last_approved=date(2026, 1, 15),
    ict_risk_function_exists=True,
    ict_risk_tolerance_documented=False,  # Gap: not yet documented
    annual_board_report_issued=True,
)

assets = [
    ICTAsset(
        name="CoreBanking-Prod",
        tier=AssetTier.CRITICAL,
        has_config_entry=True,
        business_function_mapped=True,
        last_vulnerability_scan=date(2026, 3, 20),
        mfa_enforced=True,
        encrypted_at_rest=True,
    ),
    ICTAsset(
        name="LegacyReporting-Prod",
        tier=AssetTier.IMPORTANT,
        has_config_entry=True,
        business_function_mapped=False,  # Gap
        last_vulnerability_scan=date(2026, 1, 10),  # Stale
        eol_date=date(2026, 12, 31),
        mfa_enforced=False,  # Gap
        encrypted_at_rest=True,
    ),
]

patches = [
    PatchItem(
        cve_id="CVE-2026-1234",
        severity=PatchSeverity.HIGH,
        identified_date=date(2026, 4, 1),
        patched_date=None,
        compensating_control=False,  # Overdue: 16 days, SLA 7 days
    ),
]

checker = DORAICTRiskChecker(
    governance=governance,
    assets=assets,
    patches=patches,
    has_third_party_register=True,
    has_network_segmentation=True,
    change_management_documented=True,
    data_classification_exists=True,
)

findings = checker.run()
print(json.dumps(findings.__dict__, indent=2, default=str))

Sample output:

{
  "art5_governance_score": 0.85,
  "art6_framework_score": 1.0,
  "art7_systems_score": 1.0,
  "art8_identification_score": 0.69,
  "art9_protection_score": 0.64,
  "overall_score": 0.76,
  "critical_gaps": [
    "Art.5(2): ICT risk tolerance not documented",
    "Art.8(3): 100% of critical assets not mapped... (LegacyReporting)",
    "Art.8(4): LegacyReporting scan stale",
    "Art.9(1): MFA not enforced on 50% of critical/important systems",
    "Art.9(2): 1 patches overdue SLA: CVE-2026-1234 (high): 16d open (SLA: 7d)"
  ],
  "recommendations": [
    "Priority 2: Complete ICT asset inventory...",
    "Priority 3: Enforce MFA on all critical systems..."
  ]
}

8. DORA × NIS2 Dual-Compliance Mapping

For financial entities that are also "essential" or "important" entities under NIS2 (banking, financial market infrastructure, digital infrastructure), both frameworks apply. DORA Art.1(2) establishes lex specialis: DORA takes precedence over NIS2 for matters within its scope, but NIS2 fills gaps DORA does not address.

The practical mapping for Art.5–9:

DORA RequirementNIS2 EquivalentStatus
Art.5 Board ICT governanceNIS2 Art.20 Management body obligationsDORA more specific: individual board member responsibility
Art.6 ICT risk frameworkNIS2 Art.21(1) proportionality + Art.21(2)(a) risk analysisDORA provides more granular structure
Art.8(4) Vulnerability identificationNIS2 Art.21(2)(h) vulnerability disclosureDORA adds ongoing vulnerability scanning obligation
Art.9(1) MFANIS2 Art.21(2)(i) MFA requirementIdentical — satisfying one satisfies both
Art.9(2) Patch managementNIS2 Art.21(2)(e) supply chain + Art.21(2)(h) vuln handlingAlign SLAs to satisfy both
Art.9(3) Data securityGDPR Art.32 technical security measuresSatisfy with unified controls

Practical approach for dual-regulated entities:

  1. Build a single ICT risk management framework with DORA as the primary structure
  2. Add NIS2-specific provisions as addenda (Art.21 measures checklist)
  3. Use one board report that addresses both DORA Art.6(8) and NIS2 Art.20 management reporting requirements
  4. Maintain one incident classification procedure covering DORA Art.18 criteria AND NIS2 Art.23 significant incidents

9. DORA Art.5–9: 25-Item Compliance Checklist

Use this checklist to evaluate your current state against the core Art.5–9 requirements.

Art.5: Governance

Art.6: Framework

Art.7: Systems

Art.8: Identification

Art.9: Protection

Scoring interpretation:


10. Common NCA Audit Findings Under DORA Art.5–9

Based on early supervisory observations and ECB/EBA guidance, the most frequently identified gaps include:

Governance gaps (Art.5):

Asset inventory gaps (Art.8):

Protection gaps (Art.9):

Third-party coverage (Art.6):


11. Hosting and Data Sovereignty Under DORA

DORA Art.28–30 governs ICT third-party risk management, including contractual requirements for cloud and SaaS providers. When selecting infrastructure for systems in scope, EU financial entities face a specific exposure:

The Cloud Act problem: Major US cloud providers are subject to the US CLOUD Act, which allows US government access to data stored anywhere globally — regardless of where the data physically resides. For EU financial entities holding client data, this creates a tension with GDPR Art.48 (prohibition on transfers without legal basis) and DORA's requirement that entities maintain full control over their ICT systems.

What DORA requires from infrastructure providers (Art.30):

Practical implication: Infrastructure deployed on EU-only cloud platforms — with no US-affiliated corporate structure and no data paths outside the EU — eliminates the Cloud Act exposure category entirely, rather than managing it through contractual provisions that may or may not be enforceable under US law.

This is the architecture underlying sota.io: EU-native PaaS running exclusively on EU infrastructure, without US-origin code paths, designed for financial and regulated sector workloads where DORA Art.28–30 compliance is a structural requirement rather than an afterthought.