Skip to content

canton: pin guardianGovernance on fee-charging CoreState references#41

Merged
bengtlofgren merged 1 commit into
integration/cantonfrom
fix/canton-fee-guardiangovernance-pin
Jul 16, 2026
Merged

canton: pin guardianGovernance on fee-charging CoreState references#41
bengtlofgren merged 1 commit into
integration/cantonfrom
fix/canton-fee-guardiangovernance-pin

Conversation

@bengtlofgren

Copy link
Copy Markdown

Summary

  • Emitter.PublishMessage, EmitterRegistry.RegisterEmitter, and ReplayRootRegistry.ClaimReplayRoot authenticated a caller-supplied CoreState cid by comparing only its operator field. operator does not determine guardianGovernance (fee custody's actual trust anchor), so a real or compromised operator could co-sign a second, fully valid CoreState around an attacker-controlled guardianGovernance/feeRecipient and redirect real fee payments — proven with a working PoC during review.
  • Adds a GetGuardianGovernance read choice on CoreState, an immutable guardianGovernance anchor on the three fee-charging templates, and a pin at all three call sites before every charge, alongside the existing operator check.
  • Three new regression tests build a genuine forged CoreState and confirm each charge now fails specifically on the new "guardianGovernance mismatch" check (verified by temporarily neutering the assertion and confirming the tests then fail via the "accepted a shadow CoreState" path, before reverting).

Coordination note

canton-keyed-ntt (#30) already added an identical GetGuardianGovernance choice (same name/signature/doc) for NTT's inbound VAA verification, independently, for a different call site. Whichever of these two PRs lands second should rebase and drop its now-duplicate copy — the choice only needs to exist once.

Test plan

  • dpm build clean on wormhole-core and wormhole-core-test
  • dpm test: 44/44 passing, including the 3 new regression tests
  • Confirmed the new tests fail for the right reason (temporarily disabled the new assertion, reran, watched them fail on "accepted a shadow CoreState", reverted)

https://claude.ai/code/session_01VFr5RtBKysvjdRN2nKmhMV

Emitter.PublishMessage, EmitterRegistry.RegisterEmitter, and
ReplayRootRegistry.ClaimReplayRoot authenticated a caller-supplied CoreState
cid by comparing only its operator field. operator does not determine
guardianGovernance (fee custody's actual trust anchor), so a real or
compromised operator could co-sign a second, fully valid CoreState around an
attacker-controlled guardianGovernance/feeRecipient and redirect real fee
payments -- proven with a working PoC.

Add a GetGuardianGovernance read choice (reusing the shape already added
independently on canton-keyed-ntt, so that branch can drop its duplicate on
rebase), store an immutable guardianGovernance anchor on the three
fee-charging templates, and pin it before every charge alongside the
existing operator check. Three new regression tests construct a genuine
forged CoreState and confirm each charge now fails specifically on the new
check.

Claude-Session: https://claude.ai/code/session_01VFr5RtBKysvjdRN2nKmhMV
@bengtlofgren
bengtlofgren requested a review from evan-gray as a code owner July 16, 2026 09:30
@bengtlofgren
bengtlofgren merged commit a67cb82 into integration/canton Jul 16, 2026
31 of 35 checks passed
@bengtlofgren
bengtlofgren deleted the fix/canton-fee-guardiangovernance-pin branch July 16, 2026 11:03
bengtlofgren added a commit to wormholelabs-xyz/native-token-transfers that referenced this pull request Jul 16, 2026
…ease

wormholelabs-xyz/wormhole#41 merged and cut an official DAR release
(canton-core-v0.2.0, built from integration/canton b5f88c38b). Replace the
interim local-build artifact with the released one and update its sha256
and provenance note.

Rebuilt all 4 packages and reran the full test suite against the new DAR:
37/37 passing.
bengtlofgren added a commit that referenced this pull request Jul 16, 2026
…ew) (#45)

#41 merged directly without going through PR review. Reverting the
functional changes (the GetGuardianGovernance choice, the guardianGovernance
field on Emitter/EmitterRegistry/ReplayRootRegistry, the pin assertions at
the three fee-charging call sites, and the 3 regression tests proving them)
so the fix can go through proper review this time.

Deliberately does NOT touch #44 (comment cleanup) or anything else merged
since -- only the functional pieces #41 introduced, hand-picked out of the
current tree so #44's independent comment tightening survives untouched in
the same files. Verified: dpm build clean, 41/41 tests passing (44 minus the
3 regression tests testing now-reverted functionality).

A follow-up PR (the literal git revert of this commit) will re-propose
adding this back, for review this time.
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.

1 participant