All personal data encrypted at rest
Why it matters
GDPR Art. 32 requires technical measures to ensure security appropriate to the risk, and storing personal data in plaintext is explicitly the risk the article addresses. OWASP A02 (Cryptographic Failures) lists cleartext storage of sensitive data as a top-two web vulnerability class. A single SQL injection, misconfigured read replica, or compromised database backup immediately yields every email address, phone number, SSN, and address in your system. ISO-27001:2022 A.8.24 requires cryptographic controls to protect data confidentiality — a plaintext PII column fails that control directly. CWE-311 and CWE-312 both describe this failure as enabling credential exposure and privacy violations at scale.
Severity rationale
Critical because a single database read — via injection, misconfigured backup, or insider access — exposes every user's plaintext PII with no additional barrier.
Remediation
Implement AES-256-GCM field-level encryption in lib/encryption.ts and apply it via an ORM lifecycle hook so every write encrypts and every read decrypts automatically.
// lib/encryption.ts
import { createCipheriv, createDecipheriv, randomBytes } from 'crypto'
const ALGORITHM = 'aes-256-gcm'
const KEY = Buffer.from(process.env.ENCRYPTION_KEY!, 'hex') // 32-byte key from secrets manager
export function encrypt(plaintext: string): string {
const iv = randomBytes(12)
const cipher = createCipheriv(ALGORITHM, KEY, iv)
const encrypted = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()])
const tag = cipher.getAuthTag()
return `${iv.toString('hex')}:${tag.toString('hex')}:${encrypted.toString('hex')}`
}
export function decrypt(ciphertext: string): string {
const [ivHex, tagHex, dataHex] = ciphertext.split(':')
const decipher = createDecipheriv(ALGORITHM, KEY, Buffer.from(ivHex, 'hex'))
decipher.setAuthTag(Buffer.from(tagHex, 'hex'))
return decipher.update(Buffer.from(dataHex, 'hex')) + decipher.final('utf8')
}
Generate the key with openssl rand -hex 32 and store it in your secrets manager (AWS Secrets Manager, Vercel environment variables, or similar) — never inline in code. Verify that cloud database at-rest encryption is enabled at the infrastructure level (Supabase and AWS RDS both default to encrypted volumes; confirm in your project settings).
DetectionPro
The detection method for this pattern is part of AuditBuffet Pro.
The full method (what to look for, pass and fail conditions, and how results get reported) ships inside the Data Protection Audit. The pattern definition, severity rationale, and remediation remain openly licensed under CC-BY-4.0.
External references
- cwe · CWE-311 — Missing Encryption of Sensitive Data
- cwe · CWE-312 — Cleartext Storage of Sensitive Information
- owasp:2021 · A02 — Cryptographic Failures
- gdpr · Art. 32 — Security of processing
- iso-27001:2022 · A.8.24 — Use of cryptography
- soc2:2017 · CC6.1 — Logical access security software, infrastructure, and architectures
- soc2:2017 · C1.1 — Identification and protection of confidential information
Taxons
History
- 2026-04-18·v1.0.0·Initial import from data-protection·automated
- 2026-07-06·v1.0.1·Add SOC 2 TSC mapping (CC6.1, C1.1) from the verified compliance crosswalk register (docs/compliance/).·by soc2-mapping-enrichment-ship-2