Skip to content

WNS-28 Fix WIRE-349 creator chain-kind validation - #601

Open
huangminghuang wants to merge 4 commits into
masterfrom
fix/wire-349-wns-28
Open

WNS-28 Fix WIRE-349 creator chain-kind validation#601
huangminghuang wants to merge 4 commits into
masterfrom
fix/wire-349-wns-28

Conversation

@huangminghuang

@huangminghuang huangminghuang commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Summary

  • resolve the authoritative creator chain kind from the sysio.chains registry in sysio.reserv::oncrtreserve
  • reject an attested creator kind that disagrees with the registered chain through the existing non-throwing RESERVE_CREATE_CANCELLED refund path
  • validate creator-address length against the authoritative kind: 20 bytes for EVM and 32 bytes for SVM
  • avoid persisting malformed, attacker-sized address bytes in sysio-billed cancellation tombstones
  • construct and store creator addresses and public keys using the authoritative registry kind
  • make oncnclrsv compare both payload and stored creator kinds with the resolved registry kind
  • prove the mismatch path queues the refund attestation, and cover malformed creator addresses
  • refresh the committed sysio.reserv.wasm

Root cause

oncrtreserve trusted the redundant creator_chain_kind supplied by the inbound attestation. A payload could therefore name an EVM chain while selecting the SVM public-key variant. The resulting reserve remained PENDING, but matchreserve later 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

  • source-built contract suite: 711 test cases passed
  • artifact-copy contract suite: 711 test cases passed
  • targeted local flow-reserve-lifecycle: SUCCESS, 46 phases / 157 steps in 911.9s, with the canonical heartbeat monitor and no fatal events
  • tracked and source-built WASM SHA-256: 1c6dd55b0e09e3b99f731d7f5be3f81b5ea762ec98423d1e1a6410ce910dc78f
  • generated ABI is byte-identical; no interface change
  • hygiene, submodule, workflow, configure, build, and CDT SDK freshness gates passed
  • correctness, architecture, and compliance review passes found no actionable issues

Reviewer 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.

Change-Id: I697804f02a44b93e6485a0b4b91ef25427f9de77
Change-Id: Ifc7cd1309e33b02257218b904a19a5e8c73e16e2
@huangminghuang
huangminghuang requested a review from a team September 4, 2026 01:29
heifner
heifner previously approved these changes Sep 4, 2026

@heifner heifner left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread contracts/sysio.reserv/src/sysio.reserv.cpp
Comment thread contracts/sysio.reserv/src/sysio.reserv.cpp Outdated
Comment thread contracts/tests/sysio.reserv_tests.cpp
Change-Id: Ia8da58c514a2bdf960b4ede5a00ef9f519286105
Change-Id: I6b6093c8a1794581d036eb2cb242677977162d63
@huangminghuang huangminghuang changed the title Fix WIRE-349 creator chain-kind validation WNS-28 Fix WIRE-349 creator chain-kind validation Sep 4, 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