Pre-launch adversarial security + abuse review of the open-registration surface (run on Fable) #79

Closed
opened 2026-07-11 00:29:12 +00:00 by robocub · 2 comments
Collaborator

A dedicated adversarial security + abuse review of the open-registration surface, to be run before open_registration is turned on in prod. Distinct from #41 (general understand-the-codebase review) and from the specific mitigations #77/#78 — this is the "try to break the thing strangers will poke" gut-check that gates going public.

Why a separate pass

Once open_registration = true, any Matrix user (local or federated) can DM the bot and drive link/approve. That is the first genuinely-untrusted input surface the project exposes, and it has had far less adversarial attention than the audio path. #76 proves the flow works; this proves it can't be abused.

Scope (attacker's-eye)

  • The DM command path + #71 gate — can any command, reply, code, or refusal be induced into a shared/bridged room? Can the is_command_room gate be tricked (invite races, membership-count timing)?
  • Two-sided auth bypass — can require_room_authority be satisfied without real room moderation? Can require_discord_approval be short-circuited (approval-code guessability/entropy, replay, cross-guild redemption, timeout races, the DiscordApproval channel)?
  • Quota/ban evasionmax_tenants_per_owner, owner/guild/room deny-lists: Sybil via federated MXIDs, pending-approval accounting, ban-then-recreate, guild/room normalization mismatches.
  • The link probe's permanent room-join — a hostile user making the shared bot account join arbitrary rooms; resource/state implications.
  • Identity/echo-exclusion — can an attacker impersonate a ghost/puppet identity or defeat echo-exclusion to inject/loop audio?
  • Appservice + token surface — blast radius of the shared as_token; anything a tenant can reach it shouldn't.
  • Resource exhaustion / DoS — bridge/ghost/puppet-pool exhaustion from within the allowed envelope (single-process, no per-tenant isolation yet).

Method & output

Run on Fable (highest-capability, adversarial), ideally multi-agent like the earlier whole-codebase review that filed #66–72. Output: filed findings + a go/no-go recommendation for enabling open registration.

Gate

Blocks turning open_registration on in prod. Do after #76 (flow validated) and alongside/after #77 + #78 (mitigations in place). Related: #47, #43, #41.

A dedicated **adversarial security + abuse review of the open-registration surface**, to be run **before** `open_registration` is turned on in prod. Distinct from #41 (general understand-the-codebase review) and from the specific mitigations #77/#78 — this is the "try to break the thing strangers will poke" gut-check that gates going public. ## Why a separate pass Once `open_registration = true`, any Matrix user (local or federated) can DM the bot and drive `link`/`approve`. That is the first genuinely-untrusted input surface the project exposes, and it has had far less adversarial attention than the audio path. #76 proves the flow *works*; this proves it can't be *abused*. ## Scope (attacker's-eye) - **The DM command path + #71 gate** — can any command, reply, code, or refusal be induced into a shared/bridged room? Can the `is_command_room` gate be tricked (invite races, membership-count timing)? - **Two-sided auth bypass** — can `require_room_authority` be satisfied without real room moderation? Can `require_discord_approval` be short-circuited (approval-code guessability/entropy, replay, cross-guild redemption, timeout races, the `DiscordApproval` channel)? - **Quota/ban evasion** — `max_tenants_per_owner`, owner/guild/room deny-lists: Sybil via federated MXIDs, pending-approval accounting, ban-then-recreate, guild/room normalization mismatches. - **The link probe's permanent room-join** — a hostile user making the shared bot account join arbitrary rooms; resource/state implications. - **Identity/echo-exclusion** — can an attacker impersonate a ghost/puppet identity or defeat echo-exclusion to inject/loop audio? - **Appservice + token surface** — blast radius of the shared as_token; anything a tenant can reach it shouldn't. - **Resource exhaustion / DoS** — bridge/ghost/puppet-pool exhaustion from within the allowed envelope (single-process, no per-tenant isolation yet). ## Method & output Run on **Fable** (highest-capability, adversarial), ideally multi-agent like the earlier whole-codebase review that filed #66–72. Output: filed findings + a **go/no-go recommendation** for enabling open registration. ## Gate Blocks turning `open_registration` on in prod. Do after #76 (flow validated) and alongside/after #77 + #78 (mitigations in place). Related: #47, #43, #41.
Author
Collaborator

#79 adversarial review — result: GO WITH CONDITIONS (do not announce publicly until the HIGH conditions land; keeping it quietly live is acceptable)

Ran the multi-agent review on Fable: 7 attacker-lens finders → 3 refute-by-default skeptics per finding → synthesis. 80 agents, 24 findings verified, 20 survived majority-confirmation, deduped to 6.

The good news (structurally sound)

Non-consensual bridging is structurally prevented. validate_management hard-refuses open_registration without BOTH require_room_authority and require_discord_approval, so committing a tenant needs a Matrix-room moderator AND a Discord Manage-Server approval for the exact target guild. Approval codes are CSPRNG 32^6 with atomic single-winner redemption + guild-scoped claiming; the shared as_token is never exposed to tenants; the DM-only (#71) command gate, fail-closed banlist reads, and approval-time ban re-check are all correct. The findings are DoS / abuse / reputation, not consent or auth-bypass.

Fixed + deployed to master this session

  • Finding 4 (HIGH) — FIXED (40135f6, live-verified): the per-guild cap counted a third party's pending links, letting anyone park pendings on a victim guild's public snowflake to block its onboarding. Pending is now scoped to the requester. mgmt_self_serve_link step 6b rewritten as a regression test; live PASS 58.0s.
  • Findings 2/3 (partial) — FIXED: validate_management now requires max_tenants_per_owner / max_tenants_per_guild / max_link_attempts when open_registration is on, so the public surface can no longer ship with zero velocity limiting (the "knobs off" footgun). Bounds a single MXID.

Remaining conditions before public announcement (filed)

  • #83 (HIGH) — probe pins the shared bot into attacker-named rooms; needs reap-only-probe-created-joins. (A naive leave-on-failure was implemented and backed out — it tore the bot out of active-bridge rooms; see #83 for the correct approach.)
  • #84 (HIGH) — global (cross-MXID) rate limiting + fair pending-table admission (federated-Sybil residual).
  • #85 (HIGH) — unthrottled DM invite auto-join + unrotated audit.jsonl; is_direct trust.
  • #86 (MEDIUM) — stronger require_room_authority bar + re-check at commit.

Recommendation

The surface is safe to keep quietly live (unannounced, near-zero traffic). Land #83–#85 (the HIGH DoS/abuse items) before any public announcement; #86 is a hardening follow-up. Prod already runs alpha.16 with the anti-abuse knobs ON.

## #79 adversarial review — result: **GO WITH CONDITIONS** (do not *announce* publicly until the HIGH conditions land; keeping it quietly live is acceptable) Ran the multi-agent review on Fable: **7 attacker-lens finders → 3 refute-by-default skeptics per finding → synthesis**. 80 agents, 24 findings verified, 20 survived majority-confirmation, deduped to 6. ### The good news (structurally sound) Non-consensual bridging is **structurally prevented**. `validate_management` hard-refuses `open_registration` without BOTH `require_room_authority` and `require_discord_approval`, so committing a tenant needs a Matrix-room moderator AND a Discord Manage-Server approval for the exact target guild. Approval codes are CSPRNG 32^6 with atomic single-winner redemption + guild-scoped claiming; the shared `as_token` is never exposed to tenants; the DM-only (#71) command gate, fail-closed banlist reads, and approval-time ban re-check are all correct. **The findings are DoS / abuse / reputation, not consent or auth-bypass.** ### Fixed + deployed to master this session - **Finding 4 (HIGH) — FIXED** (`40135f6`, live-verified): the per-guild cap counted a *third party's* pending links, letting anyone park pendings on a victim guild's public snowflake to block its onboarding. Pending is now scoped to the requester. `mgmt_self_serve_link` step 6b rewritten as a regression test; live PASS 58.0s. - **Findings 2/3 (partial) — FIXED**: `validate_management` now **requires** `max_tenants_per_owner` / `max_tenants_per_guild` / `max_link_attempts` when `open_registration` is on, so the public surface can no longer ship with zero velocity limiting (the "knobs off" footgun). Bounds a single MXID. ### Remaining conditions before **public announcement** (filed) - **#83 (HIGH)** — probe pins the shared bot into attacker-named rooms; needs reap-only-probe-created-joins. *(A naive leave-on-failure was implemented and backed out — it tore the bot out of active-bridge rooms; see #83 for the correct approach.)* - **#84 (HIGH)** — global (cross-MXID) rate limiting + fair pending-table admission (federated-Sybil residual). - **#85 (HIGH)** — unthrottled DM invite auto-join + unrotated `audit.jsonl`; `is_direct` trust. - **#86 (MEDIUM)** — stronger `require_room_authority` bar + re-check at commit. ### Recommendation The surface is safe to keep **quietly live** (unannounced, near-zero traffic). Land #83–#85 (the HIGH DoS/abuse items) before any public announcement; #86 is a hardening follow-up. Prod already runs alpha.16 with the anti-abuse knobs ON.
Author
Collaborator

Done. Multi-agent adversarial review (Fable; 7 finders → 3 refute-skeptics each → synthesis) — verdict GO_WITH_CONDITIONS: consent model structurally sound; all findings DoS/abuse, not auth-bypass. The blocking HIGH conditions were fixed + deployed (finding 4 + mandatory-caps in alpha.16; #83/#84/#85 in alpha.18). Remaining items are hardening follow-ups tracked in #86 (MED authority bar) and #87/#88/#89 (residuals). Full go/no-go in the comment above.

Done. Multi-agent adversarial review (Fable; 7 finders → 3 refute-skeptics each → synthesis) — verdict **GO_WITH_CONDITIONS**: consent model structurally sound; all findings DoS/abuse, not auth-bypass. The blocking HIGH conditions were fixed + deployed (finding 4 + mandatory-caps in alpha.16; #83/#84/#85 in **alpha.18**). Remaining items are hardening follow-ups tracked in #86 (MED authority bar) and #87/#88/#89 (residuals). Full go/no-go in the comment above.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
dark/nether-voicebridge#79
No description provided.