2026-06-09·5 min read·sota.io Team

EU AI Act Art.15 vs CRA Annex I: Cybersecurity Requirements Overlap and Divergence

Post #2 in the EU AI Act + CRA Dual Compliance Developer Series (5 posts)

EU AI Act Art.15 and CRA Annex I cybersecurity requirements overlap diagram

Post 1 established who falls under both regulations. This post maps what each demands on cybersecurity specifically — and where you can satisfy both with shared controls vs. where each demands something the other does not.

The short version: Art.15 focuses on the AI model's security properties during its lifecycle. CRA Annex I focuses on the product's security properties across all software components. CRA Art.12 explicitly says these layer, not substitute. Your compliance budget goes furthest when you implement shared controls once and document them against both frameworks simultaneously.

What EU AI Act Art.15 Requires

Art.15 is titled "Accuracy, robustness and cybersecurity." It applies to high-risk AI systems and demands:

Art.15(1): Accuracy levels High-risk AI systems must be designed and developed so that they achieve an appropriate level of accuracy, robustness, and cybersecurity. The appropriate levels and metrics must be declared in the technical documentation (Annex IV).

Art.15(2): Resilience against errors and inconsistencies High-risk AI systems must be resilient to errors, faults, and inconsistencies that may occur within the system or in the environment in which it operates — in particular from:

Art.15(3): Technical redundancy and fallback solutions Where relevant to product purpose, high-risk AI systems must include technical redundancy solutions, including fallbacks and fail-safe plans. This is a design requirement, not just a monitoring requirement.

Art.15(4): Robustness against adversarial attacks High-risk AI systems accessible via network interfaces must be developed with state-of-the-art cybersecurity measures to prevent unauthorised third parties from accessing, exploiting, or modifying them. This specifically calls out training data poisoning, model evasion, adversarial examples, and model extraction.

Art.15(5): Logging for cybersecurity incidents High-risk AI systems must record relevant cybersecurity-related events detected during operation. These logs feed the Art.12 record-keeping obligations and the Art.73 incident reporting trigger.

from dataclasses import dataclass
from typing import Optional, List
from enum import Enum
import logging
import hashlib
from datetime import datetime

class SecurityEventType(Enum):
    ADVERSARIAL_INPUT = "adversarial_input"
    MODEL_EXTRACTION_ATTEMPT = "model_extraction_attempt"
    DATA_POISONING_DETECTED = "data_poisoning_detected"
    AUTHENTICATION_FAILURE = "authentication_failure"
    UNAUTHORIZED_ACCESS = "unauthorized_access"
    INPUT_ANOMALY = "input_anomaly"
    OUTPUT_ANOMALY = "output_anomaly"

@dataclass
class SecurityEvent:
    event_type: SecurityEventType
    timestamp: datetime
    system_id: str
    severity: str           # critical / high / medium / low
    source_ip: Optional[str]
    request_hash: Optional[str]
    ai_decision_id: Optional[str]
    details: str

class ArtFifteenSecurityLogger:
    """
    Art.15(5)-compliant security event logger for high-risk AI systems.
    Records events required by AI Act and feeds CRA Annex I Part II vulnerability tracking.
    """
    def __init__(self, system_id: str, logger: logging.Logger):
        self.system_id = system_id
        self.logger = logger

    def log_security_event(self, event: SecurityEvent) -> str:
        """Log and return event ID for Art.12 record-keeping chain."""
        event_id = hashlib.sha256(
            f"{event.timestamp.isoformat()}{event.system_id}{event.event_type.value}".encode()
        ).hexdigest()[:16]

        self.logger.warning(
            "AI_SECURITY_EVENT",
            extra={
                "event_id": event_id,
                "event_type": event.event_type.value,
                "system_id": event.system_id,
                "severity": event.severity,
                "timestamp": event.timestamp.isoformat(),
                "ai_decision_id": event.ai_decision_id,
                "details": event.details,
                # CRA Annex I Part II: vulnerability tracking fields
                "regulatory_frameworks": ["EU_AI_ACT_ART15", "CRA_ANNEX_I_PART_II"],
            }
        )
        return event_id

    def detect_adversarial_input(self, input_vector, model_output, confidence: float) -> Optional[SecurityEvent]:
        """
        Art.15(4): detect adversarial examples and input manipulation.
        Returns SecurityEvent if anomaly detected, None otherwise.
        """
        # Low confidence + unusual input pattern = potential adversarial
        if confidence < 0.3:
            return SecurityEvent(
                event_type=SecurityEventType.ADVERSARIAL_INPUT,
                timestamp=datetime.utcnow(),
                system_id=self.system_id,
                severity="high",
                source_ip=None,
                request_hash=hashlib.sha256(str(input_vector).encode()).hexdigest()[:16],
                ai_decision_id=None,
                details=f"Low-confidence output ({confidence:.2f}) suggests potential adversarial input"
            )
        return None

What CRA Annex I Requires

CRA Annex I is split into two parts:

Part I: Security properties of the product (during design and manufacture)

The 13 essential requirements cover:

  1. No known exploitable vulnerabilities at time of placing on market
  2. Secure by default configuration
  3. Protection of data at rest and in transit (authenticity, integrity, confidentiality)
  4. Protection of data processed by the product against manipulation and unauthorised access
  5. Minimisation of data collected and processed (data minimisation)
  6. Protection of confidentiality, integrity and availability of stored, transmitted and processed data
  7. Ability to limit attack surface (reducing unused features, ports, services)
  8. Reduced impact of incidents through appropriate isolation mechanisms
  9. Record-keeping of security-relevant events (logs)
  10. Ability to perform security updates (the update pipeline obligation)
  11. Freedom from known exploitable vulnerabilities in third-party components
  12. Secure configuration by default
  13. Revocation and invalidation capability for authentication mechanisms

Part II: Vulnerability handling requirements (post-market)

  1. Identify and document vulnerabilities and components (SBOM — Art.31 + Annex VII)
  2. Address and remediate vulnerabilities without delay
  3. Apply effective coordinated vulnerability disclosure (CVD) policy
  4. Release security updates free of charge within a defined timeframe
  5. Provide vulnerability information publicly (CVE database)
  6. Apply a policy for coordinated disclosure
  7. Provide security contact information (security.txt or equivalent)
from dataclasses import dataclass, field
from typing import List, Dict, Optional
from datetime import datetime, timedelta
from enum import Enum

class VulnerabilitySeverity(Enum):
    CRITICAL = "critical"   # CVSS 9.0-10.0
    HIGH = "high"           # CVSS 7.0-8.9
    MEDIUM = "medium"       # CVSS 4.0-6.9
    LOW = "low"             # CVSS 0.1-3.9

@dataclass
class VulnerabilityRecord:
    """CRA Annex I Part II: vulnerability tracking record."""
    cve_id: Optional[str]
    component: str
    component_version: str
    severity: VulnerabilitySeverity
    discovered_at: datetime
    cvd_notified_at: Optional[datetime]     # coordinated disclosure
    patch_available_at: Optional[datetime]
    patch_released_at: Optional[datetime]
    public_disclosure_at: Optional[datetime]

    def days_to_patch(self) -> Optional[int]:
        """CRA Annex I Part II req 2: patch 'without delay'."""
        if self.patch_released_at:
            return (self.patch_released_at - self.discovered_at).days
        return None

    def is_overdue(self, severity_deadlines: Dict[VulnerabilitySeverity, int]) -> bool:
        """Check if patch is overdue per severity deadline policy."""
        deadline_days = severity_deadlines.get(self.severity)
        if deadline_days is None or self.patch_released_at:
            return False
        return (datetime.utcnow() - self.discovered_at).days > deadline_days

class SBOMManager:
    """
    CRA Art.31 + Annex VII: Software Bill of Materials management.
    Required for CRA compliance; also feeds AI Act Annex IV technical documentation.
    """
    def __init__(self):
        self.components: List[Dict] = []

    def add_component(self, name: str, version: str, license: str,
                      supplier: str, purl: Optional[str] = None) -> None:
        self.components.append({
            "name": name,
            "version": version,
            "license": license,
            "supplier": supplier,
            "purl": purl,   # Package URL — machine-readable component identifier
            "added_at": datetime.utcnow().isoformat(),
        })

    def export_cyclonedx(self) -> Dict:
        """Export CycloneDX 1.4 format — CRA-preferred SBOM format."""
        return {
            "bomFormat": "CycloneDX",
            "specVersion": "1.4",
            "version": 1,
            "components": [
                {
                    "type": "library",
                    "name": c["name"],
                    "version": c["version"],
                    "licenses": [{"license": {"id": c["license"]}}],
                    "supplier": {"name": c["supplier"]},
                    "purl": c.get("purl"),
                }
                for c in self.components
            ],
        }

The Overlap: Where Art.15 and Annex I Say the Same Thing

Cybersecurity logging

Both require security event logging:

Shared control: A single structured log pipeline (structured JSON, SIEM-forwarded) satisfies both. Label events with both regulatory references for documentation clarity.

Protection against unauthorised access

Shared control: mTLS for service-to-service communication, RBAC for data access, API authentication — document once against both frameworks.

Resilience and fail-safe design

Shared control: Circuit breakers, graceful degradation, rate limiting, and bulkhead isolation serve both requirements simultaneously.

Attack surface reduction

Shared control: Containerised deployment with minimal base images, no unnecessary services, network policies limiting model API exposure.

from typing import Protocol, runtime_checkable

@runtime_checkable
class DualComplianceSecurityControl(Protocol):
    """
    Protocol for security controls that satisfy both EU AI Act Art.15 and CRA Annex I.
    Implement this interface to get dual-framework compliance credit.
    """
    def get_art15_coverage(self) -> List[str]:
        """Return list of Art.15 requirements this control satisfies."""
        ...

    def get_cra_annex_i_coverage(self) -> List[str]:
        """Return list of CRA Annex I requirements (by number) this control satisfies."""
        ...

    def log_compliance_evidence(self) -> Dict:
        """
        Return structured evidence record for both regulatory frameworks.
        Used in technical documentation (AI Act Annex IV + CRA Art.31 Annex VII).
        """
        ...

class AuthenticationControl:
    """
    Authentication system that satisfies:
    - Art.15(4): protection against unauthorised access via network interfaces
    - CRA Annex I Part I req 3: data access protection
    - CRA Annex I Part I req 13: revocation capability
    """
    def get_art15_coverage(self) -> List[str]:
        return ["Art.15(4) — unauthorised access protection"]

    def get_cra_annex_i_coverage(self) -> List[str]:
        return ["Annex I Part I req 3 (data access)", "Annex I Part I req 13 (revocation)"]

    def log_compliance_evidence(self) -> Dict:
        return {
            "control": "api_authentication",
            "mechanism": "JWT with 1h TTL + refresh token rotation",
            "revocation": "token_blocklist_redis",
            "frameworks": {
                "EU_AI_ACT_ART15": "unauthorised_access_protection",
                "CRA_ANNEX_I_PART_I": ["req_3", "req_13"],
            },
        }

The Divergence: Where Each Demands Something Unique

What Art.15 requires that Annex I does not

Adversarial ML robustness (Art.15(4))

AI Act Art.15(4) specifically calls out adversarial examples, model evasion, training data poisoning, and model extraction as threats requiring mitigation. CRA Annex I is product-level and does not address ML-specific attack vectors.

This means dual-regulated products need:

None of these map to a CRA Annex I requirement — they are purely AI Act obligations.

Accuracy levels and metric documentation (Art.15(1))

High-risk AI systems must declare accuracy metrics in technical documentation. CRA has no equivalent requirement for product accuracy. This is an AI Act-only obligation.

Fallback solutions for AI decision continuity (Art.15(3))

The Art.15(3) requirement for fallback plans specifically addresses the scenario where the AI component fails — the system should degrade gracefully to a non-AI decision path. CRA Annex I req 8 addresses isolation but not the concept of a fallback non-AI path.

What CRA Annex I requires that Art.15 does not

SBOM and component vulnerability tracking (Annex I Part II)

CRA requires a Software Bill of Materials (Annex VII), coordinated vulnerability disclosure, and public CVE reporting. AI Act Annex IV (technical documentation) requires component documentation but does not mandate SBOM format, CVD policy, or CVE publication.

Security update delivery obligation (Annex I Part II req 4)

CRA explicitly requires that security updates be available free of charge for the support period. AI Act has no equivalent obligation — it focuses on monitoring and incident reporting, not mandatory update delivery timelines.

Secure-by-default configuration (Annex I Part I req 2 + 12)

CRA requires products to be configured securely out of the box (no unnecessary features enabled, strong defaults). AI Act does not have a secure-by-default requirement — Art.15 addresses the system's security capabilities, not its default configuration state.

Minimal data processing (Annex I Part I req 5)

CRA requires data minimisation at the product level. AI Act Art.10 addresses training data governance but does not impose a runtime data minimisation requirement equivalent to CRA Annex I req 5.

@dataclass
class DualComplianceGap:
    """Track requirements that don't map between frameworks."""
    requirement: str
    framework: str          # "AI_ACT_ART15" or "CRA_ANNEX_I"
    maps_to_other: bool
    standalone_control_needed: str

DIVERGENCE_MAP: List[DualComplianceGap] = [
    # AI Act-only obligations
    DualComplianceGap(
        requirement="Art.15(1) — accuracy metrics",
        framework="AI_ACT_ART15",
        maps_to_other=False,
        standalone_control_needed="ModelAccuracyMonitor with metric tracking in technical docs"
    ),
    DualComplianceGap(
        requirement="Art.15(4) — adversarial ML robustness",
        framework="AI_ACT_ART15",
        maps_to_other=False,
        standalone_control_needed="AdversarialInputDetector + training data integrity verification"
    ),
    DualComplianceGap(
        requirement="Art.15(3) — fallback to non-AI path",
        framework="AI_ACT_ART15",
        maps_to_other=False,
        standalone_control_needed="FallbackDecisionEngine for AI component failure"
    ),
    # CRA-only obligations
    DualComplianceGap(
        requirement="Annex I Part II — SBOM + CVE publication",
        framework="CRA_ANNEX_I",
        maps_to_other=False,
        standalone_control_needed="SBOMManager + CVD policy + security.txt"
    ),
    DualComplianceGap(
        requirement="Annex I Part II req 4 — free security updates",
        framework="CRA_ANNEX_I",
        maps_to_other=False,
        standalone_control_needed="Documented patch SLA + free update delivery pipeline"
    ),
    DualComplianceGap(
        requirement="Annex I Part I req 2+12 — secure by default",
        framework="CRA_ANNEX_I",
        maps_to_other=False,
        standalone_control_needed="Hardened default configuration + CIS Benchmark alignment"
    ),
]

CRA Art.12: The Bridge Article

CRA Art.12 explicitly addresses high-risk AI systems: where a product with digital elements is also a high-risk AI system under the EU AI Act, the CRA's Annex I requirements apply in addition to the AI Act's cybersecurity requirements. They do not replace or substitute each other.

The practical implication: you cannot satisfy CRA Annex I by pointing to AI Act Art.15 compliance documentation, and vice versa. Each framework requires its own evidence trail, even where the underlying technical control is identical.

What CRA Art.12 does allow: where both frameworks require logging, for example, a single log pipeline with dual-framework documentation satisfies both. The evidence documents once, maps twice.

Compliance Documentation Strategy

The most efficient approach is a shared control register that maps each technical control to all regulatory requirements it satisfies:

from typing import Dict, List, Any

class DualComplianceControlRegister:
    """
    Single source of truth for technical controls satisfying both
    EU AI Act Art.15 and CRA Annex I — documentation strategy for Annex IV + CRA Art.31.
    """
    def __init__(self, system_id: str, system_name: str):
        self.system_id = system_id
        self.system_name = system_name
        self.controls: List[Dict[str, Any]] = []

    def register_control(
        self,
        control_id: str,
        description: str,
        implementation: str,
        ai_act_mappings: List[str],      # e.g. ["Art.15(4)", "Art.15(5)"]
        cra_annex_i_mappings: List[str], # e.g. ["Part I req 3", "Part I req 9"]
        evidence_location: str,
    ) -> None:
        self.controls.append({
            "control_id": control_id,
            "description": description,
            "implementation": implementation,
            "mappings": {
                "EU_AI_ACT": ai_act_mappings,
                "CRA_ANNEX_I": cra_annex_i_mappings,
            },
            "evidence": evidence_location,
        })

    def export_for_technical_docs(self) -> Dict:
        """Export for AI Act Annex IV technical documentation."""
        return {
            "system": self.system_name,
            "framework": "EU AI Act Art.15 + CRA Annex I",
            "controls": self.controls,
        }

# Example registration
register = DualComplianceControlRegister("ai-saas-prod", "AutoRecruitAI")

register.register_control(
    control_id="SEC-001",
    description="Structured security event logging with SIEM forwarding",
    implementation="JSON-structured logs via structlog → Loki → Grafana",
    ai_act_mappings=["Art.15(5) — cybersecurity event recording"],
    cra_annex_i_mappings=["Part I req 9 — security-relevant data recording"],
    evidence_location="logs/security_events/*.log + docs/sec-001-compliance.md",
)

register.register_control(
    control_id="SEC-002",
    description="API authentication with token revocation",
    implementation="JWT RS256 + Redis blocklist + 1h TTL",
    ai_act_mappings=["Art.15(4) — unauthorised access protection"],
    cra_annex_i_mappings=["Part I req 3 — data access protection", "Part I req 13 — revocation"],
    evidence_location="src/auth/ + docs/sec-002-compliance.md",
)

register.register_control(
    control_id="SEC-003",
    description="Adversarial input detection",
    implementation="Confidence threshold monitoring + input anomaly scoring",
    ai_act_mappings=["Art.15(4) — adversarial attack resilience"],
    cra_annex_i_mappings=[],   # AI Act-only — no CRA equivalent
    evidence_location="src/ml/adversarial_detector.py + docs/sec-003-compliance.md",
)

Timeline Summary

RequirementDeadlineFramework
AI Act Art.15 cybersecurity for high-risk AIAugust 2, 2026EU AI Act
CRA Chapter IV (notified body notifications)June 11, 2026CRA
CRA Art.14 reporting obligations (24h/72h/14-day)September 11, 2026CRA
CRA full manufacturer obligations incl. Annex IDecember 11, 2027CRA

For dual-regulated products, August 2, 2026 is the first hard deadline: AI Act Art.15 compliance must be documented in your Annex IV technical documentation by then. CRA Annex I has until December 2027 for full compliance, but CRA Art.14 incident reporting applies from September 11, 2026 — four months after the AI Act deadline.

Developer Checklist: Art.15 + Annex I Shared Controls

Implement these once, map to both frameworks:

AI Act-only (Art.15 requires, Annex I does not):

CRA-only (Annex I requires, Art.15 does not):

EU-Hosted Infrastructure as a Compliance Simplifier

One factor simplifies both frameworks simultaneously: where your product runs. Art.15(4) specifically addresses threats via network interfaces. CRA Annex I Part I addresses data access and modification. Both frameworks' threat models assume the infrastructure provider is outside your control and potentially subject to foreign jurisdiction access.

When infrastructure runs on EU-native hosting (like sota.io on Hetzner Germany) with no US-parent exposure, you remove an entire class of threats from your Art.15(4) and Annex I threat model: covert foreign government access via CLOUD Act-style requests to your cloud provider. This simplifies your compliance documentation for both frameworks — the threat is eliminated at the infrastructure layer, not mitigated by additional controls.

Post 3 covers the incident reporting layer: CRA Art.14 reporting obligations versus AI Act Art.73 incident reporting — and how to build a unified incident pipeline that satisfies both.

EU-Native Hosting

Ready to move to EU-sovereign infrastructure?

sota.io is a German-hosted PaaS — no CLOUD Act exposure, no US jurisdiction, full GDPR compliance by design. Deploy your first app in minutes.