Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Risk Register — brain-server (ISO 42001 Annex A / EU AI Act Art 9)

Source: THREAT_MODEL.md (STRIDE) + SECURITY.md (OWASP Top 10:2025) + AUDIT.md ledger (55 findings).
Purpose: the table a Stage-1 auditor asks for — ID · description · likelihood × impact · treatment · owner · residual. This file is the COMPLIANCE.md §6.1 / Art 9 pointer.
Update rule: add a row when a STRIDE entry or an AUDIT finding adds a new risk; close a row only when the treatment is pinned by a test and the AUDIT.md disposition is closed. Keep likelihood/impact honest (no scoring inflation).

IDRisk (STRIDE)LikelihoodImpactTreatment (shipped or ceiling)OwnerResidual
R-01Cross-tenant read via missing AuthZ gate (A01)LowHighJWT tenant from signed claim only + per-route authorize() at handler entry (v1.2, test-pinned AUTHZ_GATES) + per-record access_scope deny-by-defaultbrain-serverLow — row-level filter, not file-level in shim mode
R-02Tampered audit log (T/R)LowHighKeyed HMAC-SHA256 chain (epoch + head pin, v1.27.31) + /audit/verify + brain_audit_chain_ok gauge; detects SQL/app tampering, not host compromisebrain-server + operator (LUKS)Low (app layer), Medium (host — operator disk encryption)
R-03Memory injection / poisoning (I/LITL)MediumHighASI06 posture: origin/source per row + blocklist+quarantine (screen) + untrusted:true + proposal gate (BRAIN_WRITE_POSTURE=review) + content_digest 409; ONNX classifier opt-in (injection-classifier)brain-server + deployer (review queue)Medium — heuristic screen, NFKC/homoglyph folding is ceiling (zero-dep rule)
R-04PII disclosure in recall/ingestMediumHighRead-time deterministic redaction (no pii_map), access_scope min-necessary filter, strict masking [redacted:*] at write boundary (v1.14.2)brain-serverLow
R-05Unauthenticated access (S)LowHighLoopback-first defaults, fail-closed on non-loopback with no auth (v1.20.29), opaque bearer (constant-time) or JWT/JWS + OIDC discovery (v1.2), /.well-known/* single public-path source (Blackout)brain-serverLow
R-06Token replay / algorithm confusion (S)LowHighALLOWED_ALGS whitelist before key lookup (RS256/RS384/RS512/ES256/ES384/EdDSA, none/HS*/PS* rejected), (jti,iss) denylist on EVERY request (per-request, zero staleness — v1.28.85), refresh-chain reuse detection burns familybrain-serverLow — no staleness window; unavailability fails closed
R-07Channel/out forgery, steering laundering (S/T)LowHighRESERVED_OUTBOX_TOPICS at enqueue_child → 400 topic_reserved, post_steering is approve-role gated + args truth (X-W1/X-L1, Wardline + Truthglass)brain-serverLow
R-08Image/beacon exfiltration (I)LowHighDoc-mode images default OFF + operator allowlist, favicon proxy default OFF, data: ≤64 KiB (Shutter); markdown refs stripped at read seambrain-server + operator (allowlist is trust)Low (doc-mode), Medium (bare URLs linkified-but-inert by contract)
R-09Supply-chain / transitive dep (T)LowHighcargo audit in CI, pinned Cargo.lock, SBOM per release (CycloneDX), minimal optional features; Marvin (rsa crate, RUSTSEC-2023-0071): the pinned direct dep is rsa = "=0.10.0-rc.18" (still the affected line, per THREAT_MODEL — no fixed release exists anywhere as of the 2026-08-04 verification; jsonwebtoken 11 rides the same disposition), accepted with the local-daemon timing model; a 0.9.10 copy survives only transitivelybrain-serverLow — Marvin is documented ignore
R-10Denial of service — burst / vector query (D)MediumMediumPer-IP tiered rate limiting (per-tenant buckets are NOT shipped — the shared-bucket gap is X-A10’s accepted residual), capacity envelopes (507 on ingest, reads never blocked), per-token/byte HTTP limits, MAX_NOTES_PER_RUN=1000brain-server + reverse proxyLow (loopback), Medium (shared loopback bucket X-A10 until per-principal)
R-11Encryption at rest (I)LowHighNo app-level encryption at rest; operator LUKS/FileVault is the layer — standing statement: DB + .bak PLAINTEXT on primary, encryption law covers follower only; SQLCipher per-tenant keys v3.7 horizonoperatorMedium until v3.7
R-12Unwarranted erasure / litigation hold miss (R)LowHighDSAR / /purge are Admin-only, explicit + tombstoned + audited; legal_holds freezes every erasure path (409 legal_hold_active, deferred held_ids on cert)brain-serverLow
R-13Egress allowlist bypass (I)LowHighInsert-only RwLock<HashMap> allowlist, validate-on-first-use, IANA special-purpose tables, BRAIN_EGRESS_ALLOW_PRIVATE=1 loud opt-out (Deadbolt)operator (BRAIN_EGRESS_*)Low — allowlisted host is trust
R-14Revocation lookup cost (S)LowLowPer-request (jti,iss) registry lookup — ZERO staleness (fieldless per-request RevocationCache, v1.28.85; the “60s negative-cache TTL” cell this row carried was the debunked claim, re-stamped T7-03 seventh pass); hot reload not shipped (PEM drop + restart X-A3b)operatorLow — residual is registry unavailability, which fails closed
R-15Loop exec escapes its boundary (T)LowHighTyped sandbox seam, policy-outranks-backend: deny-default sandbox-exec (Seatbelt) profiles on macOS, target-gated Landlock enforcement on Linux; unavailable backend refuses the command rather than running unconfined; Drop kills and reaps on every path out; env-cleared spawn (src/workflow/sandbox.rs, v1.28.92)brain-serverLow — profile content is operator trust
R-16Agent mints obligations or record rows (E)LowHighMachine-refusal law at surface AND core: decision_ref REQUIRED, screened and bounded, on handoff decision / back-referral return / pipeline transition / account archive; account link + pipeline rows agent-denied end to end; role gates refuse the agent class before any row is written (v1.28.92)brain-serverLow — a mis-scoped operator token is the residual, audited per transition
R-17Bulk-read exfiltration via record layers (I)LowHighBoth bulk surfaces (disagreement-corpus export, account listing) require Admin scope AND DPO role, land a global audit row per call (principal, filter, row count), answer bounded pages only; corpus de-identifies at the seam through a synthetic scope-less reader and rows carry their frozen train/holdout partition (v1.28.92)brain-server + DPOLow — the DPO role grant itself is the trust point
R-18Corpus poisoning via reflection capture (T)LowMediumReflection derives ONLY from audited gate rows (gdl_gate / control:adversarial_recheck / handoff_lifecycle) — agent free text can never mint a disagreement tuple; capture is proven retrospective-only (same case twice byte-identical); must-miss catalog fail-closed on parse (src/workflow/gdl.rs, redflags_domains.json, v1.28.92 / 1.32.7)brain-serverLow — catalog keyword coverage is heuristic, the forcing function is not

Scale note (ISO 42001 Clause 6.1): Likelihood is assessed for the loopback-first, single-process deployment that this repo ships. A non-loopback, multi-tenant internet deployment moves R-01/R-10 to Medium likelihood until per-principal rate buckets + file-level tenant isolation ship — note this in the procurement response.

Traceability: every row above maps to a THREAT_MODEL.md STRIDE entry and/or an AUDIT.md finding. Keep this file in sync — CONTACT_CENTER_STANDARDS.md and COMPLIANCE.md §6.1 point here as the Art 9 / ISO 42001 Clause 6.1 evidence.

Next review trigger: any STRIDE change, any AUDIT ledger add/close. (The “Loop line (v1.32.x) landing” trigger has FIRED — the Loop shipped through 1.32.7 in v1.28.92 and the 1.29.x line continues it — and the review was performed in the v1.28.92–v1.29.2 window: no new register row, no disposition change; this note replaces the standing trigger, whose condition no longer distinguishes anything.)