GDPR Art.32: Security of Processing — Technical & Organizational Measures, Encryption & Developer Checklist (2026)
Post #444 in the sota.io EU Cyber Compliance Series
Article 32 is the GDPR's security mandate for every data controller and processor. Where Article 25 (Privacy by Design) is about building privacy in from the start, Article 32 is about maintaining security during ongoing operations. It applies to every organization — from a two-person SaaS to a hyperscaler — that processes personal data of EU residents, and it underpins supervisory authority fines across every GDPR enforcement action where a breach occurred.
The article does not prescribe a fixed list of controls. Instead it establishes a risk-based proportionality framework: the measures you implement must be appropriate to the risk. Cheap measures are not automatically adequate; expensive ones are not automatically required. The test is whether the chosen TOMs appropriately reduce the likelihood and severity of harm to data subjects.
Art.32 at a Glance
| Paragraph | Rule | Applies To |
|---|---|---|
| Art.32(1) | Implement appropriate TOMs considering state of the art, cost, nature, scope, context, purposes, and risk | Controller + Processor |
| Art.32(1)(a)–(d) | Four specific TOM categories (see below) | Controller + Processor |
| Art.32(2) | Assess risks: accidental/unlawful destruction, loss, alteration, unauthorised disclosure or access | Controller + Processor |
| Art.32(3) | Adherence to Art.40 Codes of Conduct or Art.42 Certification may demonstrate compliance | Controller + Processor |
| Art.32(4) | Persons acting under controller/processor authority only process data on instruction | Controller + Processor |
The Four TOM Categories (Art.32(1)(a)–(d))
GDPR Art.32(1) enumerates four non-exhaustive TOM categories. These are not a closed list — they illustrate the minimum floor of expectation:
(a) Pseudonymisation and Encryption of Personal Data
Pseudonymisation (Art.4(5)): replacing direct identifiers with pseudonyms so data can no longer be attributed to a specific data subject without the use of additional information, which is kept separately. Encryption: rendering data unreadable without the correct key.
Developer obligations:
- Encrypt personal data at rest (AES-256 or equivalent) in databases, backups, and storage volumes.
- Encrypt personal data in transit (TLS 1.2 minimum; TLS 1.3 recommended for new services).
- Separate encryption keys from the encrypted data — a breach of the database alone should not expose plaintext.
- Pseudonymise data for analytics, testing, and secondary processing where re-identification is not required.
- Rotate encryption keys on a documented schedule; store keys in a hardware security module (HSM) or managed KMS (AWS KMS, GCP Cloud KMS, Azure Key Vault, or EU-sovereign equivalent).
(b) Ongoing Confidentiality, Integrity, Availability, and Resilience
The CIA triad extended with resilience — the ability of systems to withstand and recover from failures, attacks, and disruptions.
Developer obligations:
- Confidentiality: Role-based access control (RBAC); principle of least privilege; MFA for all administrative access.
- Integrity: Database constraints, checksums, write-ahead logging, signed audit trails.
- Availability: Redundant infrastructure, load balancing, no single points of failure for personal data stores.
- Resilience: Design for failure — chaos engineering, graceful degradation, circuit breakers. EU-hosted PaaS infrastructure (e.g., sota.io) that runs in single-tenant EU data centres provides additional resilience isolation compared to multi-region hyperscalers where data can unexpectedly transit non-EU regions.
(c) Ability to Restore Availability and Access in Timely Manner After Incident
This is the GDPR's business continuity obligation for personal data. After an incident — ransomware, hardware failure, accidental deletion — you must be able to restore access to personal data within a timeframe appropriate to the risk.
Developer obligations:
- Automated backups on a documented schedule (daily minimum; hourly for high-sensitivity data).
- Offsite backup storage: backups must be stored separately from the primary data — a single-region database backup stored in the same account is not sufficient.
- Tested restore procedures: document RTO (Recovery Time Objective) and RPO (Recovery Point Objective) for all personal data stores. Test quarterly.
- Incident response plan: documented procedure for containing breaches, assessing scope, notifying DPA within 72h (Art.33), and notifying data subjects where required (Art.34).
(d) Process for Regularly Testing, Assessing, and Evaluating Effectiveness of TOMs
Security is not a one-time configuration — it is an ongoing process. Art.32(1)(d) requires a documented, recurring review cycle.
Developer obligations:
- Penetration testing: annual minimum for systems processing special category data or processing at scale; document findings and remediation.
- Vulnerability scanning: automated SAST/DAST in CI/CD pipelines; dependency scanning (SCA) for known CVEs.
- Security code review: peer review with security checklist for all changes touching personal data flows.
- Log review: alerting on anomalous access patterns; SIEM or equivalent.
- TOM review: annual review of all TOMs against updated threat landscape and ENISA recommendations.
Art.32(2): Risks to Account For
Art.32(2) specifies the risk categories controllers and processors must consider when calibrating their TOMs:
"In assessing the appropriate level of security account shall be taken in particular of the risks that are presented by processing, in particular from accidental or unlawful destruction, loss, alteration, unauthorised disclosure of, or access to, personal data transmitted, stored or otherwise processed."
| Risk Category | Examples | TOM Mitigation |
|---|---|---|
| Accidental destruction | Server hardware failure, fire, flood | Geo-redundant backups, disaster recovery plan |
| Unlawful destruction | Insider threat, ransomware | Immutable backups, access logging, MFA |
| Accidental loss | Developer deletes production table | Backup verification, change-control process |
| Alteration | Data corruption, malicious modification | Integrity checks, audit trail, signed commits |
| Unauthorised disclosure | Data breach, misconfigured S3 bucket | Encryption at rest, access control, DAST |
| Unauthorised access | Credential theft, privilege escalation | MFA, RBAC, session management, zero-trust |
Art.32(3): Codes of Conduct and Certification as Compliance Proof
Adherence to an approved Art.40 Code of Conduct or possession of an Art.42 certification may be used as an element to demonstrate compliance with Art.32 requirements. This is a compliance shortcut, not a safe harbour — supervisory authorities can still find inadequate security even with a certification if the specific risk was not addressed.
Relevant certifications and standards:
- ISO/IEC 27001: International standard for information security management systems (ISMS). Widely accepted by EU DPAs as evidence of systematic TOM implementation.
- SOC 2 Type II: Common in US-origin SaaS; EU DPAs increasingly accept it but prefer ISO 27001.
- BSI C5: German Federal Office for Information Security cloud attestation — recognised by German DPA (BfDI).
- EUCS (EU Cloud Certification Scheme): ENISA scheme under the EU Cybersecurity Act; final version under adoption (2026). Expected to become the EU-native standard for cloud processor compliance.
- CSA STAR: Cloud Security Alliance; useful supplementary evidence.
For small SaaS operators not yet certified, ENISA's Guidelines on Minimum Security Measures for Digital Service Providers and ENISA's Cloud Security Guide for SMEs provide a practical TOM baseline referenced by DPAs in enforcement.
Relationship to Other GDPR Articles
Art.32 does not operate in isolation:
| Related Article | Relationship |
|---|---|
| Art.24 — Controller Responsibility | Art.24 is the overarching controller obligation to implement appropriate measures; Art.32 specifies the security subset |
| Art.25 — Privacy by Design/Default | Art.25 requires TOMs at design time; Art.32 requires them at all times during processing. Overlapping but distinct obligations. |
| Art.28 — Processor Agreements | Art.28(3)(c) requires the DPA to impose Art.32 obligations on the processor. The controller must verify the processor's TOMs contractually. |
| Art.35 — DPIA | A DPIA identifies risks; Art.32 requires mitigating them with TOMs. High-risk DPIA findings must be reflected in Art.32 measures. |
| Art.33 — Breach Notification (72h) | Art.32(1)(c) restore obligation + Art.33 notification are the two operational responses to a security incident. |
| Art.34 — Communication to Data Subjects | Required when a breach is likely to result in high risk — directly triggered when Art.32 TOMs were inadequate to prevent harm. |
| Art.83(4) — Administrative Fines | Art.32 violations: up to €10 million or 2% of global annual turnover (whichever is higher). |
ENISA TOM Recommendations (2026 Baseline)
ENISA's Recommendations on Security Measures for Article 32 of the GDPR (last updated 2024, referenced in 2026 enforcement actions) identify the following minimum baseline for SaaS and cloud processors:
Identity and Access:
- MFA for all privileged accounts (administrative access, database access, production deployments).
- Service-to-service authentication using short-lived credentials (OAuth 2.0 client credentials, OIDC workload identity) — not long-lived API keys stored in environment variables.
- Quarterly access reviews; immediate de-provisioning on employee offboarding.
Network Security:
- TLS 1.3 for all data in transit; TLS 1.2 as minimum floor.
- Network segmentation: personal data stores not directly accessible from the public internet.
- Web Application Firewall (WAF) for all HTTP/S endpoints processing personal data.
Logging and Monitoring:
- Tamper-evident audit logs for all access to personal data (who accessed what, when, from where).
- Log retention: minimum 12 months; 6 months online, 6 months cold storage.
- Alerting: anomalous access patterns (off-hours bulk exports, privilege escalation, failed logins) trigger incident response.
Vulnerability Management:
- SAST in CI/CD (static analysis for injection, XXE, SSRF, authentication bypass).
- Dependency scanning: automated CVE alerts for all third-party libraries; P0 CVEs patched within 24h.
- Annual penetration test by an external party; findings tracked to closure.
Data Minimisation and Masking:
- Production personal data never copied to development/staging environments — use synthetic data or pseudonymised exports.
- Query-level access controls: application service accounts cannot run full-table exports of personal data.
EU-Hosted PaaS and Art.32
For developers choosing a PaaS provider to host applications processing personal data, Art.32 creates direct obligations on the processor (the PaaS). Under Art.28(3)(c), the PaaS must implement TOMs at least equivalent to those the controller has specified in the DPA.
EU-native PaaS providers (such as sota.io) offer a structural advantage: data sovereignty guarantees that personal data never leaves the EU, eliminating the class of Art.32 risks arising from cross-border transfer to jurisdictions with weaker security enforcement frameworks. GDPR enforcement in 2026 has increasingly cited processor TOM inadequacy in cross-border transfer scenarios as a compounding factor in breach fines — DPAs are looking not just at what happened but at whether the controller took adequate steps to ensure the processor's TOMs were sufficient.
Key questions to ask your PaaS provider for Art.32 compliance:
- Do you hold ISO 27001, BSI C5, or EUCS certification?
- Where is personal data physically stored? (Requirement: EU data centres only)
- What is your incident notification SLA? (GDPR requires you be notified in time to meet the 72h Art.33 deadline)
- Do you provide tamper-evident audit logs of all access to your infrastructure where personal data resides?
- What is your key management architecture? (Customer-managed keys preferred)
Enforcement Landscape (2026)
Art.32 violations are among the most frequently cited articles in DPA fines, often in conjunction with Art.33 (breach notification) and Art.5(1)(f) (integrity and confidentiality principle):
| Case | DPA | Fine | Art.32 Violation |
|---|---|---|---|
| Meta Ireland (2023) | Irish DPA | €91M | Passwords stored in plaintext (no encryption at rest) |
| British Airways (UK, 2020) | ICO | £20M | Inadequate security controls; SQL injection vector |
| Marriott International (UK, 2020) | ICO | £18.4M | Acquired vulnerable infrastructure; no due-diligence TOM review |
| CNIL vs. e-commerce operator (FR, 2022) | CNIL | €150,000 | No TLS 1.2 minimum; personal data in HTTP URLs |
| German hospital (DE, 2023) | BfDI | €105,000 | No MFA on administrative access; inadequate logging |
| Dutch telecom (NL, 2021) | AP | €475,000 | Password reset via knowledge-based authentication only; no MFA |
Pattern: encryption, access controls, and logging are the three most common Art.32 deficiencies cited in fines.
Python Implementation: SecurityAuditRecord
from dataclasses import dataclass, field
from datetime import date, datetime
from enum import Enum
from typing import Optional
import hashlib
import json
class EncryptionStatus(Enum):
COMPLIANT = "compliant" # AES-256 at rest + TLS 1.3 in transit
PARTIAL = "partial" # Encrypted in transit only
NON_COMPLIANT = "non_compliant" # Plaintext storage detected
class MFAStatus(Enum):
ALL_PRIVILEGED = "all_privileged" # MFA on all admin/DB/deploy accounts
PARTIAL = "partial" # MFA on some privileged accounts
ABSENT = "absent" # No MFA
@dataclass
class TOMAssessment:
"""Art.32(1)(a)–(d) four-category TOM assessment."""
encryption_at_rest: EncryptionStatus
encryption_in_transit: EncryptionStatus
pseudonymisation_in_use: bool
mfa_status: MFAStatus
rbac_implemented: bool
backup_tested_rto_hours: Optional[int] # None = not tested
backup_offsite: bool
pen_test_date: Optional[date] # None = never tested
vuln_scanning_in_ci: bool
audit_logging_enabled: bool
log_retention_days: int
incident_response_plan: bool
def art_32_1a_score(self) -> str:
"""Encryption and pseudonymisation (Art.32(1)(a))."""
if (self.encryption_at_rest == EncryptionStatus.COMPLIANT and
self.encryption_in_transit == EncryptionStatus.COMPLIANT and
self.pseudonymisation_in_use):
return "COMPLIANT"
if (self.encryption_at_rest == EncryptionStatus.NON_COMPLIANT or
self.encryption_in_transit == EncryptionStatus.NON_COMPLIANT):
return "NON_COMPLIANT"
return "PARTIAL"
def art_32_1b_score(self) -> str:
"""Confidentiality, integrity, availability, resilience (Art.32(1)(b))."""
if (self.mfa_status == MFAStatus.ALL_PRIVILEGED and
self.rbac_implemented and
self.audit_logging_enabled):
return "COMPLIANT"
if self.mfa_status == MFAStatus.ABSENT:
return "NON_COMPLIANT"
return "PARTIAL"
def art_32_1c_score(self) -> str:
"""Restore availability after incident (Art.32(1)(c))."""
if (self.backup_offsite and
self.backup_tested_rto_hours is not None and
self.backup_tested_rto_hours <= 4 and
self.incident_response_plan):
return "COMPLIANT"
if not self.backup_offsite or not self.incident_response_plan:
return "NON_COMPLIANT"
return "PARTIAL"
def art_32_1d_score(self) -> str:
"""Regular testing and evaluation of TOMs (Art.32(1)(d))."""
pen_test_current = (
self.pen_test_date is not None and
(date.today() - self.pen_test_date).days <= 365
)
if (pen_test_current and
self.vuln_scanning_in_ci and
self.log_retention_days >= 365):
return "COMPLIANT"
if not self.vuln_scanning_in_ci and self.pen_test_date is None:
return "NON_COMPLIANT"
return "PARTIAL"
@dataclass
class SecurityAuditRecord:
"""Art.32 GDPR security audit record — produce annually or after significant changes."""
system_name: str
data_controller: str
audit_date: date
tom_assessment: TOMAssessment
auditor: str
certifications: list[str] = field(default_factory=list) # ["ISO 27001", "BSI C5"]
open_findings: list[str] = field(default_factory=list)
remediation_deadline: Optional[date] = None
def overall_status(self) -> str:
scores = [
self.tom_assessment.art_32_1a_score(),
self.tom_assessment.art_32_1b_score(),
self.tom_assessment.art_32_1c_score(),
self.tom_assessment.art_32_1d_score(),
]
if all(s == "COMPLIANT" for s in scores):
return "ART_32_COMPLIANT"
if any(s == "NON_COMPLIANT" for s in scores):
return "ART_32_NON_COMPLIANT"
return "ART_32_PARTIAL"
def generate_audit_hash(self) -> str:
"""Tamper-evident hash of audit record for audit trail."""
record_str = json.dumps({
"system": self.system_name,
"date": str(self.audit_date),
"status": self.overall_status(),
"auditor": self.auditor,
}, sort_keys=True)
return hashlib.sha256(record_str.encode()).hexdigest()[:16]
def to_report(self) -> dict:
return {
"audit_id": f"ART32-{self.audit_date.strftime('%Y%m%d')}-{self.generate_audit_hash()}",
"system": self.system_name,
"controller": self.data_controller,
"audit_date": str(self.audit_date),
"overall": self.overall_status(),
"tom_scores": {
"32_1a_encryption_pseudonymisation": self.tom_assessment.art_32_1a_score(),
"32_1b_cia_resilience": self.tom_assessment.art_32_1b_score(),
"32_1c_restore_after_incident": self.tom_assessment.art_32_1c_score(),
"32_1d_regular_testing": self.tom_assessment.art_32_1d_score(),
},
"certifications": self.certifications,
"open_findings": self.open_findings,
"remediation_deadline": str(self.remediation_deadline) if self.remediation_deadline else None,
}
# Example: SaaS startup processing user personal data
assessment = TOMAssessment(
encryption_at_rest=EncryptionStatus.COMPLIANT,
encryption_in_transit=EncryptionStatus.COMPLIANT,
pseudonymisation_in_use=True,
mfa_status=MFAStatus.ALL_PRIVILEGED,
rbac_implemented=True,
backup_tested_rto_hours=2,
backup_offsite=True,
pen_test_date=date(2026, 2, 15),
vuln_scanning_in_ci=True,
audit_logging_enabled=True,
log_retention_days=365,
incident_response_plan=True,
)
audit = SecurityAuditRecord(
system_name="UserDataPlatform",
data_controller="Acme GmbH",
audit_date=date(2026, 4, 18),
tom_assessment=assessment,
auditor="External Security Partner GmbH",
certifications=["ISO 27001:2022"],
open_findings=[],
)
import pprint
pprint.pprint(audit.to_report())
# Output: {audit_id: ART32-20260418-..., overall: ART_32_COMPLIANT, ...}
Developer Checklist: GDPR Art.32 Compliance
Use this checklist for each system processing personal data. Revisit annually and after significant architecture changes.
Encryption (Art.32(1)(a))
- Personal data encrypted at rest (AES-256 or stronger)
- Personal data encrypted in transit (TLS 1.3; minimum TLS 1.2)
- Encryption keys stored separately from encrypted data (HSM or KMS)
- Key rotation schedule documented and automated
- Pseudonymisation applied where re-identification is not required
Access Control (Art.32(1)(b))
- MFA enforced for all administrative, database, and deployment accounts
- RBAC implemented: users and services have minimum required permissions
- Service-to-service auth uses short-lived credentials (no long-lived API keys in env vars)
- Access review performed quarterly; offboarding de-provisioning immediate
Availability and Resilience (Art.32(1)(b)+(c))
- Automated backups on documented schedule (daily minimum)
- Offsite / cross-region backup storage
- Backup restore tested within last 6 months; RTO/RPO documented
- Incident response plan documented and reviewed annually
- No single point of failure for personal data stores
Ongoing Testing (Art.32(1)(d))
- SAST and dependency scanning in CI/CD pipeline
- Annual penetration test by external party; findings tracked to closure
- Tamper-evident audit logging for all access to personal data
- Log retention: minimum 12 months
- Alerting on anomalous access patterns (bulk export, off-hours, privilege escalation)
Documentation
- Art.32 TOM assessment documented (this checklist + SecurityAuditRecord)
- TOMs referenced in Art.28 DPA with each processor
- Annual TOM review scheduled and tracked
Common Developer Mistakes
1. Encrypting in transit but not at rest. TLS protects data moving across the network; it does nothing for data sitting in a database or backup. Both layers are required under Art.32(1)(a).
2. No MFA on database administrative access. Production database credentials stolen via phishing or credential stuffing is the single most common Art.32 violation. MFA on the infrastructure layer (SSH, cloud console, database management tool) blocks the majority of these attacks.
3. Backups stored in the same account / region as production. Ransomware targeting your primary storage will also target backups in the same AWS account. Offsite means a different account or provider — ideally air-gapped.
4. Never testing the restore procedure. A backup that has never been restored is not a backup — it's an assumption. Art.32(1)(c) requires the ability to restore, which requires evidence that restoration works.
5. Production personal data in development environments. Developers who copy production data to local machines or staging environments to debug issues create an uncontrolled personal data store with no Art.32 controls. Use synthetic or pseudonymised data in all non-production environments.
6. Long-lived API keys as service credentials. Service accounts authenticating with static API keys stored in environment variables or source code are one accidental git commit away from a breach. Use workload identity, OIDC tokens, or secrets managers with short-lived credentials.
Summary
GDPR Art.32 requires every controller and processor to implement appropriate technical and organizational measures — calibrated to risk — across four categories: encryption and pseudonymisation, CIA+resilience, restore capability, and regular testing. The article is risk-based: there is no universal minimum set of controls, but encryption at rest and in transit, MFA on privileged access, offsite tested backups, and documented security testing are the baseline expectations confirmed by ENISA guidance and DPA enforcement patterns.
For developers building on EU-sovereign infrastructure, Art.32 compliance integrates naturally with a PaaS provider that already implements the infrastructure-layer TOMs (encryption, resilience, access controls) and documents them in the Art.28 DPA — leaving the application layer (RBAC, audit logging, security testing) as the developer's responsibility.
Related posts:
- GDPR Art.25: Privacy by Design & Default
- GDPR Art.28: Processor Agreements & DPAs
- GDPR Art.33–34: Breach Notification (72h)
- GDPR Art.35: DPIA
- GDPR Art.36: Prior Consultation — when DPIA shows high residual risk, Art.36 consultation package requires complete TOM documentation