Skip to content

fix(state): cap RotateChannelKey + Event.deps (SEC-V-07)#452

Merged
intendednull merged 1 commit into
auto-fix/batch-2026-04-28-002530from
auto-fix/issue-236-rotate-deps-caps
Apr 28, 2026
Merged

fix(state): cap RotateChannelKey + Event.deps (SEC-V-07)#452
intendednull merged 1 commit into
auto-fix/batch-2026-04-28-002530from
auto-fix/issue-236-rotate-deps-caps

Conversation

@intendednull
Copy link
Copy Markdown
Owner

What

Cap two attacker-controlled vectors. Stop ManageChannels-holder flooding state.channel_keys w/ ~7000 fabricated entries per RotateChannelKey. Stop any author bloating Event.deps.

Refs #236 (SEC-V-07).

Caps

  • MAX_EVENT_DEPS = 64 — checked in EventDag::insertInsertError::DepsTooLong.
  • MAX_ENCRYPTED_KEY_BYTES = 128 — checked in EventDag::insert for each blob inside RotateChannelKey.encrypted_keysInsertError::EncryptedKeyTooLarge.
  • MAX_ENCRYPTED_KEYS_OVER_MEMBERS = 4 — epsilon added to state.members.len() ceiling. Checked in apply_event for RotateChannelKeyApplyResult::Rejected.

Tier choice

  • Caps needing no state context → EventDag::insert (fires for every code path: local + inbound wire, since all events go through insert).
  • Member-count cap → apply_event (needs state.members).

Runner-up: stuff all three into Event::new. Rejected. Event::new infallible today; changing signature cascades to ~25 callsites for zero extra coverage — every event passes through dag.insert before touching state.

Downstream

willow-replay::role::try_insert matches InsertError exhaustively. Added warn! arms for the two new variants.

Tests (state crate, 5 added)

  • dag_insert_rejects_deps_over_cap
  • dag_insert_accepts_deps_at_cap
  • dag_insert_rejects_oversized_encrypted_key
  • apply_rotate_channel_key_rejects_excess_entries_over_member_count
  • apply_rotate_channel_key_accepts_at_member_count_plus_epsilon

Local gate

  • cargo fmt --check clean
  • cargo clippy --workspace --all-targets -- -D warnings clean
  • cargo test --workspace 227 willow-state + all downstream pass
  • cargo check --target wasm32-unknown-unknown (state + client + web etc) clean

Sub-PR base ≠ main → CI not firing. Local check is the gate.

https://claude.ai/code/session_01VdcwSdvqig423A5CX2fSzR


Generated by Claude Code

Anti-DoS caps for two attacker-controlled vectors that fan out via
.clone() into per-peer state. Ref #236.

Caps + tier:
- MAX_EVENT_DEPS = 64. EventDag::insert rejects oversize deps with
  InsertError::DepsTooLong. Author-side path covered too because every
  event reaches `insert` before reaching state.
- MAX_ENCRYPTED_KEY_BYTES = 128. EventDag::insert rejects oversize
  per-blob payloads inside RotateChannelKey.encrypted_keys with
  InsertError::EncryptedKeyTooLarge. One X25519-sealed key fits well
  under that.
- MAX_ENCRYPTED_KEYS_OVER_MEMBERS = 4. apply_event for
  RotateChannelKey rejects when encrypted_keys.len() exceeds
  state.members.len() + epsilon. Needs state context, so it lives at
  apply time alongside the existing member gate.

Tier choice: caps that need no state context go at the DAG insert
boundary so they fire regardless of which call path produced the
event. The member-count cap requires `state.members` and naturally
slots into the existing apply_event Rejected branch.

Runner-up: stuffing all three into Event::new. Rejected because
Event::new is currently infallible and changing it cascades to ~25
production + test callsites for no extra coverage — every event
already passes through dag.insert before mutating state.

willow-replay matches on InsertError exhaustively; added warn arms
for the two new variants.

Tests (state crate, 5 added):
- dag_insert_rejects_deps_over_cap
- dag_insert_accepts_deps_at_cap
- dag_insert_rejects_oversized_encrypted_key
- apply_rotate_channel_key_rejects_excess_entries_over_member_count
- apply_rotate_channel_key_accepts_at_member_count_plus_epsilon

Local: cargo fmt --check, cargo clippy --workspace --all-targets
-D warnings, cargo test --workspace, cargo check --target
wasm32-unknown-unknown all green.

https://claude.ai/code/session_01VdcwSdvqig423A5CX2fSzR
@intendednull intendednull merged commit 7ee7e0a into auto-fix/batch-2026-04-28-002530 Apr 28, 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.

2 participants