Skip to content

fix: F-2026-18190 | [Dual Defense] Obsolete TSS Keyshares Survive Quorum Change Without Deletion or Retirement - #305

Open
Aman035 wants to merge 7 commits into
audit-fixesfrom
F-2026-18190
Open

fix: F-2026-18190 | [Dual Defense] Obsolete TSS Keyshares Survive Quorum Change Without Deletion or Retirement#305
Aman035 wants to merge 7 commits into
audit-fixesfrom
F-2026-18190

Conversation

@Aman035

@Aman035 Aman035 commented Aug 17, 2026

Copy link
Copy Markdown
Member

F-2026-18190 — Obsolete TSS keyshares survive quorum change

Problem

  • keyshare.Manager had no delete API, so predecessor shares were never removed.
  • Quorum change preserves the TSS pubkey, so old shares stay usable for the live vault key — including on a validator that has left the quorum.

Fix

  • keyshare.Manager: added List() and Delete(id) (overwrite + unlink, idempotent).
  • pushcore.GetAllKeys(): wraps the existing AllKeys RPC for key history.
  • New tss/keysharegc sweeper, wired into tss.go. Deletes a share only when all hold:
    • not the current key ID
    • its tss_pubkey equals the current key's pubkey
    • no TSS process pending
    • no pending fund migration references it
  • Any RPC error skips the sweep instead of deleting on partial state.

Why these rules

  • Pubkey equality, not process type: same pubkey = redundant. Different pubkey = rotated-away key that fund migration still needs to sweep the old vault.
  • Pending-process guard instead of a grace period: Push has instant finality, so there is no reorg window. The real risk is that a missing share during quorum change is silently read as "new party".
  • Retired-pubkey shares are not auto-deleted: a chain whose migration was never initiated looks the same as one with nothing to migrate, and guessing wrong strands funds.

Deviations from the recommendation

  • Not deleting "after stored and voted" — voting isn't finalization, and deleting there could destroy a still-current share if the ballot never reaches quorum. We read CurrentKey from chain instead.
  • Did not implement "refuse non-current key IDs": fund migration signs with a non-current key by design.

Tests: 20 subtests covering delete/keep rules, pending-process skip, fail-closed on each RPC error, and the new List/Delete.

Severity: Low (needs offline multi-host compromise; shares are encrypted at rest).

@Aman035 Aman035 changed the title fix: delete keyshares superseded by quorum change or key refresh (F-2026-18190) fix: F-2026-18190 | [Dual Defense] Obsolete TSS Keyshares Survive Quorum Change Without Deletion or Retirement Aug 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant