# Threat-model review history

The threat model is SPEC §2.1 (what must remain impossible), with the mathematical triage in [MATH.md](/stability-policy.md) and the [boundary register](/boundary-register.md).

This page lists the reviews that changed it. Each is recorded at the fix site in the code and pinned by a test. **No named external reviewer has reviewed Mirror yet.** When one does, they are listed here with their consent, and not before.

| Review | What it found | What changed | Pinned by |
|---|---|---|---|
| Leg authentication (internal, marked Sev-0 at the fix site) | With unsigned legs accepted, the operator's signature was the only thing behind a clear: the operator could copy one member's commitments into another's slot | Strict leg signing is the default; the opt-out expires on 2026-12-01 and cannot be extended | `server/core.js`, `server/cutover.test.js` |
| Blind join key (internal, Sev-0) | A plaintext shipment reference let the operator's logs draw the correspondent graph | Locator commitments; plaintext refused after the cutover date | `kernel/mirror-locator.js`, `server/cutover.test.js` |
| Transport (internal) | The operator API had no HSTS or CSP while the static site did; `HEAD /jwks` returned 404 | Security headers on every response; HEAD routed as GET | `worker/src/index.js`, `server/app.js` |
| Strategy review: independent witnesses (September 2026) | Two desks stating the same number could mint a clear | The independence gate: no clear without a ratified witness | `kernel/mirror-independence-gate.js`, `server/independence-gate-routes.test.js` |
| The mathematical gaps (September 2026) | A label is not proven to be its value's band; malleable signatures; the pricing basis is not compared; pairwise secrets | Precise assertion (`not_proven_here`), origin binding, basis commitment, low-S signatures, pairwise ECDH; the ZK proof commissioned rather than hand-rolled | `MATH.md`, `server/label-integrity-routes.test.js`, `kernel/mirror-malleability.test.js` |
| Deal-gate review (September 2026) | Procurement blockers: custody, rotation, push delivery, per-desk permissions, API description | HSM custody, rehearsed rotation, signed webhooks, delegated scoped keys, OpenAPI 3.1, signed provenance | `server/webhooks.test.js`, `server/delegation.test.js`, `server/rotation-rehearsal.test.js`, `server/openapi.test.js` |
| This round's own tests (September 2026) | A failover bander re-signing the same legs was counted as a second verdict; an unreachable HSM produced a silently unbandable batch; an unrecordable governance event could split isolates | The idempotency key ignores signature bytes; the bander stops when the HSM stops; events are durable before they change state | `server/bander-ha.test.js`, `server/degradation.test.js` |

## What an external review would be asked to attack first

- The independence gate and the witness registry: can a stakeholder obtain a witness-class key?
- The raw-data wall's key normalisation, against the [published corpus](/sar-smuggles.json).
- Delegation and scope enforcement: can a delegate widen its scopes or outlive a revocation?
- Webhook delivery: SSRF through DNS rebinding and redirects.
- The claim in `/cannot` that the operator can hold no staff directory and no secret.
