GDPR Article 17 deletion path exists and is tested
Why it matters
GDPR Article 17 grants EU residents the right to erasure of their personal data — and it is not optional for any system that serves EU users. Without a coded deletion path, every right-to-erasure request requires manual database surgery by an engineer, which is slow, error-prone, and leaves no audit trail. CWE-212 (Improper Removal of Sensitive Information Before Storage or Transfer) covers the broader pattern of not handling PII lifecycle correctly. CCPA §1798.105 grants California residents similar rights. An untested deletion path is nearly as risky as no deletion path: without automated verification, the cascade almost certainly misses tables, leaving PII silently intact.
Severity rationale
High because the absence of a coded, tested deletion path means every erasure request is a manual intervention with no audit trail, making GDPR Art. 17 and CCPA §1798.105 compliance undemonstrable and costly to operationalize.
Remediation
Implement a deletion service in src/lib/compliance/deletion.ts that anonymizes PII in place (preserving aggregate integrity) and writes an erasure receipt. Add at least one test that asserts PII is gone after the call:
// src/lib/compliance/deletion.ts
export async function processErasureRequest(
contactId: string,
requestedBy: string
): Promise<ErasureReceipt> {
const startedAt = new Date()
await db.contact.update({
where: { id: contactId },
data: {
email: `deleted-${contactId}@erasure.invalid`,
firstName: null,
lastName: null,
phone: null,
deletedAt: startedAt
}
})
const receipt = await db.erasureAuditLog.create({
data: { contactId, requestedBy, processedAt: startedAt, tablesAffected: ['contacts', 'consent_records'] }
})
return { receiptId: receipt.id, processedAt: startedAt }
}
// src/__tests__/erasure.test.ts
it('removes PII from contacts table', async () => {
const contact = await createTestContact({ email: 'test@example.com' })
await processErasureRequest(contact.id, 'test-runner')
const after = await db.contact.findUnique({ where: { id: contact.id } })
expect(after?.email).not.toContain('test@example.com')
})
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 Compliance & Consent Engine Audit. The pattern definition, severity rationale, and remediation remain openly licensed under CC-BY-4.0.
External references
- gdpr · Art. 17 — Right to erasure (right to be forgotten)
- ccpa · §1798.105 — Right to deletion
- cwe · CWE-212 — Improper removal of sensitive information before storage or transfer
- nist:rev5 · MP-6 — Media sanitization
Taxons
History
- 2026-04-18·v1.0.0·Initial import from compliance-consent-engine·automated