WNS-28 Fix WIRE-349 creator chain-kind validation - #601
Conversation
Change-Id: I697804f02a44b93e6485a0b4b91ef25427f9de77
Change-Id: Ifc7cd1309e33b02257218b904a19a5e8c73e16e2
heifner
left a comment
There was a problem hiding this comment.
Reviewed against the CertiK WNS-28 report. The fix is correct and complete for the reported issue.
What I checked beyond the diff itself:
The premise holds. sysio.msgch::dispatch_reserve_create binds ext.chain_code to the proven delivering outpost, then forwards rc.creator_addr.kind verbatim — so chain_code is proven and the creator kind is free-form payload, exactly as reported.
The invariant cannot drift. regchain is the only writer of a chain row's kind; activchain and setoutpost do not touch it, and there is no erase. A registered code's kind is therefore immutable, which is what makes resolving it independently in oncrtreserve and matchreserve sufficient rather than needing the kind pinned on the reserve row.
Consistent with existing precedent. sysio.uwrit::swapfromwire already enforces the same registry-kind equality for recipient_kind, so this brings oncrtreserve in line rather than introducing a new pattern.
The committed WASM carries the fix. Since CI deploys the checked-in artifact as-is, I checked the binary rather than the source: the new rejection string is present in the committed wasm and absent from the base. The ABI is untouched, consistent with the unchanged action signature.
The regression test is genuine. authex::recordlink does not validate key type against chain_kind, and bypubkey is keyed on the key hash with no kind component — so pre-fix the SVM-linked ED key would have resolved as linked and produced a PENDING row. The test fails without the change.
Reclaim interaction is sound. A mismatched create against a live PENDING row hits the existing-row guard; against a CANCELLED row it takes the no-double-refund branch. Neither clobbers a legitimate reserve.
One design question, not a blocker: the mismatch adds a new trigger for writing a CANCELLED tombstone and queueing a refund on a triple that a legitimate creator can later reclaim. The comments here assume the outpost refunds idempotently per (chain, token, reserve_code). If a tombstone refund can land after a reclaiming creator's escrow is already locked, that is a cross-chain desync — pre-existing on the unlinked-creator path, but this widens the trigger set. Worth confirming against the outpost side.
Three minor notes inline, none blocking.
Separately, I filed SEC-158 for the same unvalidated-payload-kind pattern in sysio.dclaim::onreward, where it is reachable through the staking-reward path and the consequence is a replay-cursor bypass rather than a stuck row. Out of scope for this PR.
Change-Id: Ia8da58c514a2bdf960b4ede5a00ef9f519286105
Change-Id: I6b6093c8a1794581d036eb2cb242677977162d63
Summary
sysio.chainsregistry insysio.reserv::oncrtreserveRESERVE_CREATE_CANCELLEDrefund pathoncnclrsvcompare both payload and stored creator kinds with the resolved registry kindsysio.reserv.wasmRoot cause
oncrtreservetrusted the redundantcreator_chain_kindsupplied by the inbound attestation. A payload could therefore name an EVM chain while selecting the SVM public-key variant. The resulting reserve remainedPENDING, butmatchreservelater used the registry-owned EVM kind and could never match the creator key.The follow-up review also identified that the creator address itself was not length-checked against that authoritative kind. The final implementation rejects both kind and address-shape mismatches through the same idempotent cancellation/refund path.
Validation
flow-reserve-lifecycle: SUCCESS, 46 phases / 157 steps in 911.9s, with the canonical heartbeat monitor and no fatal events1c6dd55b0e09e3b99f731d7f5be3f81b5ea762ec98423d1e1a6410ce910dc78fReviewer notes
The handler retains its never-throw dispatch semantics. Unregistered chains still soft-skip, while a registered-chain kind or address mismatch follows the idempotent cancellation/refund path used for malformed or unlinked creators. Invalid creator-address bytes are cleared before the cancellation tombstone is stored; the outpost refund remains keyed by the reserve triple.
Current-head CI and targeted remote flow evidence are pending for this pushed revision.