File: crates/state/src/server.rs:199
Severity: security
Obvious? no
meets_threshold evaluates Count(n) as yes_count >= (n as usize).min(admin_count); with n = 0 the right-hand side is 0, so the predicate is true for every non-negative yes_count. There is no n >= 1 validation anywhere on the path — apply_proposed_action::SetVoteThreshold blindly stores the threshold supplied in the payload (materialize.rs:240-242).
Bypass: the genesis owner (or any admin who can muster majority once) emits Propose { action: SetVoteThreshold { threshold: Count(0) } }. The proposer auto-yes records yes_count = 1, the owner_override or majority passes the threshold change, and from then on every Propose from any admin auto-applies on its sole proposer-yes vote. A hostile admin can now Propose { GrantAdmin { ... } } or Propose { KickMember { genesis_author } } and it lands with zero peer votes — turning a multi-admin server into a single-admin dictatorship via one threshold change.
Fix: clamp on the apply side: let n = n.max(1); state.vote_threshold = VoteThreshold::Count(n.min(state.admins.len() as u32)) (or reject the apply outright on n == 0). Also enforce the floor in meets_threshold for defense in depth: Count(n) => yes_count >= (n as usize).clamp(1, admin_count).
Filed by /general-audit @ 88498a5 (2026-05-04). master: #600.
File:
crates/state/src/server.rs:199Severity: security
Obvious? no
meets_thresholdevaluatesCount(n)asyes_count >= (n as usize).min(admin_count); withn = 0the right-hand side is0, so the predicate istruefor every non-negativeyes_count. There is non >= 1validation anywhere on the path —apply_proposed_action::SetVoteThresholdblindly stores the threshold supplied in the payload (materialize.rs:240-242).Bypass: the genesis owner (or any admin who can muster majority once) emits
Propose { action: SetVoteThreshold { threshold: Count(0) } }. The proposer auto-yes recordsyes_count = 1, the owner_override or majority passes the threshold change, and from then on everyProposefrom any admin auto-applies on its sole proposer-yes vote. A hostile admin can nowPropose { GrantAdmin { ... } }orPropose { KickMember { genesis_author } }and it lands with zero peer votes — turning a multi-admin server into a single-admin dictatorship via one threshold change.Fix: clamp on the apply side:
let n = n.max(1); state.vote_threshold = VoteThreshold::Count(n.min(state.admins.len() as u32))(or reject the apply outright onn == 0). Also enforce the floor inmeets_thresholdfor defense in depth:Count(n) => yes_count >= (n as usize).clamp(1, admin_count).Filed by
/general-audit@88498a5(2026-05-04). master: #600.