Provenance fields are immutable after creation
Why it matters
Provenance fields that can be overwritten are not provenance — they are annotations. If an enrichment job can silently replace source_id or acquired_at on an existing contact, the audit trail is broken. GDPR Art. 5(1)(d) requires data accuracy, which includes accuracy about the origin of the data. SLSA Provenance L2 requires that provenance records be unforgeable after creation. CWE-345 (Insufficient Verification of Data Authenticity) applies when records can be modified post-creation in ways that destroy traceability.
Severity rationale
High because mutable provenance fields allow enrichment jobs or admin tools to silently rewrite the record of origin, breaking GDPR Art. 30 compliance and destroying the evidentiary value of the audit trail.
Remediation
Exclude provenance fields from all update schemas at the application layer, and optionally enforce immutability at the database layer with a trigger.
// Zod update schema in src/lib/contacts/update.ts
const updateContactSchema = z.object({
email: z.string().email().optional(),
first_name: z.string().optional(),
last_name: z.string().optional(),
// source_type, source_id, acquired_at intentionally excluded
})
-- Database-level enforcement
CREATE OR REPLACE FUNCTION prevent_provenance_update()
RETURNS TRIGGER LANGUAGE plpgsql AS $$
BEGIN
IF NEW.source_type IS DISTINCT FROM OLD.source_type OR
NEW.source_id IS DISTINCT FROM OLD.source_id OR
NEW.acquired_at IS DISTINCT FROM OLD.acquired_at THEN
RAISE EXCEPTION 'Provenance fields are immutable after creation';
END IF;
RETURN NEW;
END;
$$;
CREATE TRIGGER enforce_provenance_immutability
BEFORE UPDATE ON contacts
FOR EACH ROW EXECUTE FUNCTION prevent_provenance_update();
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 Sourcing & Provenance Audit. The pattern definition, severity rationale, and remediation remain openly licensed under CC-BY-4.0.
External references
- cwe · CWE-345 — Insufficient Verification of Data Authenticity
- slsa:1.0 · Provenance L2 — Provenance is authenticated and tamper-evident
- gdpr · Art. 5(1)(d) — Accuracy — provenance modification could invalidate lawful basis record
- gdpr · Art. 30 — Records of processing activities
Taxons
History
- 2026-04-18·v1.0.0·Initial import from data-sourcing-provenance·automated