Files
amethyst/quartz
Claude a42499435b fix(marmot): enforce required_capabilities on Add and Welcome (RFC 9420 §7.2)
When a group installs a `required_capabilities` extension (every Marmot
group does, listing MarmotGroupData=0xF2EE, SelfRemove=0x000A, Basic
credential), every member's leaf MUST advertise those types in its own
[Capabilities]. We were validating none of that:

- `applyProposalAdd` checked version + ciphersuite but never matched the
  new KP's capabilities against the group's required_capabilities. A
  non-conformant member silently joined; the next commit that touched
  their leaf got rejected by spec-conformant peers, splitting the group.
- `processWelcome` similarly never checked the joiner's own KP against
  the group's required set, nor did it sweep existing members' leaves.
  A misconfigured GroupInfo signer could invite us into an incoherent
  group whose first commit we'd silently reject forever.

Adds two helpers in `MlsGroup.Companion`:
- `findRequiredCapabilities(extensions)`: decodes the §7.2 struct from
  a GroupContext extension list, or returns null if absent.
- `requireCapabilitiesMeetRequirements(caps, req, who)`: throws with a
  specific (extensions=, proposals=, credentials=) diff naming the
  missing types — turns silent interop breaks into one debuggable line.

Wires the gate in two places:
- `applyProposalAdd` rejects the Add proposal if the new leaf falls
  short of the group's required set.
- `processWelcome` rejects the join if either (a) our own KP doesn't
  meet the group's requirements or (b) any existing member's leaf
  doesn't — the latter catches a malformed GroupInfo at join time.

5 new tests: round-trip decoding, rejection on missing extension /
proposal, acceptance when caps are a superset, and an end-to-end
`addMember` rejection of a hand-crafted KP with SelfRemove stripped
(re-signed so the rejection is from the capability gate, not the
signature check). Quartz test suite green; marmot interop 16/16.

Closes audit gaps #4, #5, #10.

https://claude.ai/code/session_013VYkpz8P1mPh9Ejxy9anhJ
2026-04-25 04:22:42 +00:00
..