Security & disclosure

Tell us how it breaks.

Mirror’s whole claim is a property you should be able to attack: that the operator cannot read a value. If you can break that, we want to hear it before a launderer does — and we will say so publicly when you do.

5 bug classes named up frontsafe harbour for good-faith researchno paid bounty yet

The bugs worth finding

Five ways to break a stated guarantee.

Named up front, because a disclosure policy that hides its own soft spots is theatre. Beside each, the code that is meant to stop it and the test that says it does — start there.

01

The operator recovers a band.

Any way the reconciliation operator can read a value, a band, or a corridor from what it receives — short of guessing a properly generated 256-bit secret.

What stands in the way

Per-shipment salts, HMAC-SHA256 under the corridor secret, in kernel/mirror-kernel.js; a secret below 128 bits is refused by kernel/mirror-secret.js. Whoever holds the secret can guess — that is Boundary 5, not a finding.

02

A forged verdict verifies.

A signed reconciled whose inputs were never submitted by the members it names, that still passes the offline verifier.

What stands in the way

ES256, low-S only, over canonical JSON (kernel/envelope.js, kernel/mirror-sign.js); legs signed by their own bank and re-joined by the verifier (kernel/mirror-leg.js). Try it on the Clear File: forge a clear and watch it fail.

03

A raw figure crosses the wire.

Any input that carries a value, unit, quantity, price, band, salt or filing decision past the operator’s wall.

What stands in the way

The raw-data wall and the tipping-off wall in server/core.js, before any route reads a body (400 raw_leaked, 400 sar_wall). The refused fields and 81 published disguises are the place to begin.

04

A clear that should not clear.

A path to a signed clear through a missing leg, mixed corridor tables, equivocation, or a mis-banded on-edge value.

What stands in the way

Fail-closed reconciliation in kernel/mirror-kernel.js — doubt is undetermined, never a clear — and the independence gate in kernel/mirror-independence-gate.js: no independent witness, no clear. The named scenarios pin each path.

05

The spec and the code disagree.

The spec hash does not match the served spec, or a conformance vector does not reproduce.

What stands in the way

The operator signs the spec’s sha256; server/vectors.test.js regenerates the vectors from the kernels on every build. Re-derive them yourself on the conformance page, or rebuild a release from its provenance.

Scope

What to test, and what to leave alone.

In scope

  • The protocol and its kernels — this repo’s crypto and fail-closed logic
  • The operator at mirror-operator.vasileburuian94.workers.dev
  • The landing site and the console
  • The on-prem bander binary
  • The Clear File and the conformance vector pack

Out of scope

  • The Cloudflare and Supabase platforms themselves — report to them
  • Denial of service by brute volume — the operator is rate-limited by design
  • Missing security headers already covered here — tell us if one regressed
  • Social engineering of the maintainer, and physical attacks
  • That a counterparty can see the shared band — a documented boundary, not a bug: Boundary 5 of the Boundary Register

Safe harbour

Good-faith research is authorised.

Good-faith, in-scope research that avoids privacy violations, data destruction, and service degradation is authorised, and we will not initiate legal action over it. Use only test data and corridors you control.

If you are unsure whether something is in scope, ask first.

There is no paid bounty yet.When there is an entity and a budget there will be one, and it will be named here rather than implied.