Pre-Birth Admission Control — 07 Intentional Misuse & Bypass Analysis
07 — Intentional Misuse & Bypass Analysis
Goal: think like a hostile/careless internal actor and find every way to create an object without a valid permit. For each: is it already blocked, detectable only, or still bypassable, plus mitigation and whether it can be absolute-deny or only monitored.
Key truth up front: birth_registry/dot_tools/pivot/gate functions are owned by app-role directus, and the live operator role workflow_admin is superuser. No in-database control is absolute against a superuser — a superuser can SET any GUC, ALTER TABLE … DISABLE TRIGGER, or DROP a constraint. Therefore the honest security model is: absolute-deny for ordinary roles; fail-closed + loud detection + audit for privileged roles. Claiming absolute prevention against superuser would be a fake-PASS (open-goal law §5).
Legend: 🔴 still bypassable · 🟡 detectable only · 🟢 blocked (for ordinary roles)
| # | Attack | Today | After pilot design | Mitigation | Absolute-deny? |
|---|---|---|---|---|---|
| 1 | Direct psql INSERT without permit (ordinary role) | 🔴 (gate advisory) | 🟢 for enforced family (gate consumes permit + deferred constraint raises) | gate extension + deferred constraint | YES for ordinary role |
| 2 | Directus/API INSERT without permit | 🔴 | 🟢 same path (triggers fire regardless of client) | same | YES for ordinary role |
| 3 | Superuser INSERT (workflow_admin) |
🔴 | 🔴 can disable trigger / set bypass | drift monitor + violation view + break-glass audit | NO — monitor only |
| 4 | SET app.bypass_birth_gate='true' |
🔴 silent | 🟡 detectable | replace w/ logged break-glass (doc 05 §4); born row w/o break-glass ledger = critical finding | NO — detect |
| 5 | code NULL (gate skips) |
🔴 | 🟢 for enforced family: require code NOT NULL; synthetic-code path also requires a permit |
gate extension: no null-code skip for enforced families | YES for ordinary role |
| 6 | Duplicate entity_code |
🔴 ON CONFLICT DO NOTHING silently drops birth |
🟢 after composite-unique fix (entity_code, collection_name) |
composite unique + conflict target change | YES |
| 7 | entity_code collision across collections (PIV-101) |
🔴 (the live defect) | 🟢 same composite-unique fix | prerequisite migration | YES |
| 8 | ALTER TABLE … DISABLE TRIGGER |
🔴 | 🔴 (superuser) | event-trigger / trigger_registry drift monitor → finding on any disabled birth/gate trigger |
NO — detect |
| 9 | CREATE TABLE outside registry | 🟡 onboarding scan (collection-granular, idle) | 🟡 | registry-driven coverage scan + DDL event trigger logging new tables | NO — detect |
| 10 | CREATE filesystem DOT file outside registry | 🟢 detected (v_dot_fs_reconciliation FILE_NO_REGISTRY=16) |
🟢 detected | reconciler already live; registrar must be sole creation path | NO — detect (FS has no DB hook) |
| 11 | Register DOT without file | 🟢 detected (v_dot_registry_no_file) |
🟢 | reconciler live | NO — detect |
| 12 | Create permit, never consume | n/a | 🟢 visible + auto-expire | watchdog → EXPIRED; v_birth_admission_permit_status shows aging RESERVED |
YES (no harm; identity never silently held) |
| 13 | Consume permit for WRONG collection/code | n/a | 🟢 | permit keyed (collection, entity_code); gate matches TG_TABLE_NAME + NEW.code; mismatch → no consume → blocked |
YES |
| 14 | Replay same permit (double-insert) | n/a | 🟢 | UNIQUE(request_hash) + single-use consumed_at + (collection,entity_code) live-permit unique |
YES |
| 15 | Expire permit, then insert | n/a | 🟢 | gate requires status RESERVED; EXPIRED permit is not consumable → blocked |
YES |
| 16 | Governance handoff worker not running | 🟡 (it isn't) | 🟡 | queue_heartbeat silent-gap finding; register-before-emit means births captured to event_pending, not lost |
NO — detect, no data loss |
| 17 | Scanner not running (pg_cron absent) | 🔴 (no scheduler) | 🟡 | external scheduler + heartbeat; missing tick = finding | NO — detect (needs scheduler) |
| 18 | Hardcoded family list misses a new family | 🔴 (16-table gate list, critical_family flag) | 🟡 | registry-driven coverage (doc 08) + STOP-on-mismatch check before any flip | NO — eliminate hardcode |
| 19 | CREATE OR REPLACE the gate fn to a no-op |
🔴 (superuser) | 🔴 | function-hash drift monitor (store approved pg_get_functiondef hash; alarm on change) |
NO — detect |
| 20 | Insert into a birth_registry_auto-only table (150 ungated) |
🔴 (no BEFORE gate) | 🟡 report-only finding (deferred constraint in report mode) | extend gate coverage registry-driven, family-by-family | NO until coverage expands |
Synthesis
What pre-birth admission makes ABSOLUTE (for ordinary roles): #1, #2, #5, #6, #7, #12–#15 — i.e. the core promise "no valid permit → no object" holds against any non-superuser caller, and the permit cannot be replayed, mis-targeted, or used after expiry.
What remains DETECT-ONLY (privileged/structural): #3, #4, #8, #19 (superuser can always bypass in-DB — answer is loud audit + drift hashes + break-glass ledger, never a false claim of prevention); #9, #10, #11, #16, #17, #20 (structural/scheduler/coverage — answered by reconciler + heartbeat + registry-driven coverage expansion).
The one thing that turns "policy" into "enforcement": flipping the family to blocking + the deferred constraint trigger. Without it (today), even #1/#2 are merely warnings. This is why the macro's honest answer is "birth-first is not enforced today" — the enforcing flip is owner/OSPA-gated and not performed here.
Highest-leverage mitigations to build first:
- composite-unique
(entity_code, collection_name)— kills #6/#7 and unblocks 5 pivots. - function/trigger drift monitor (hash of
pg_get_functiondeffor the gate + birth fns; disabled-trigger detector) — converts #3/#4/#8/#19 from invisible to loud. - registry-driven coverage + STOP-on-mismatch — kills #18 and bounds #20.