fix(governance-api): require the signed message to match the submitted body#779
Closed
frankmeds wants to merge 1 commit into
Closed
fix(governance-api): require the signed message to match the submitted body#779frankmeds wants to merge 1 commit into
frankmeds wants to merge 1 commit into
Conversation
…d body The signature was verified over body.sig.message, but every downstream check (validation, gZIL gate, IPFS pin, DB record) uses body.msg. A client could sign one string and submit a different proposal/vote body, which would then be treated as authentic. Reject when body.sig.message !== body.msg, before signature verification. Applies to both EVM and Schnorr paths. Verified safe against real prod (ZilPay) and staging (EVM) data: sig.message already equals body.msg for all legitimate submissions.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem (pre-existing authenticity gap)
In
POST /api/message, the signature is verified overbody.sig.message, but every downstream check — message validation, the gZIL gate, the IPFS pin, and the DB record — operates onbody.msg(JSON.parse(body.msg)). Nothing ties the two together.A client could therefore sign one string and submit a different proposal/vote body: the signature check passes (over
sig.message), while the unsignedbody.msgis accepted and persisted as authentic. This affects both the EVM and Schnorr paths and predates the EVM work (surfaced during the #778 security review).Fix
Reject the request when
body.sig.message !== body.msg, before signature verification:Byte-equality is the correct check: the signature authenticates the exact bytes of
sig.message, so those bytes must equal thebody.msgbytes that produce the content.Safety (verified against real data, no behaviour change for legitimate clients)
The current frontend builds both from the same string (
msg.msg), so they're already identical. Confirmed empirically: for all sampled prod gZIL proposals (ZilPay/Schnorr) and staging duck proposals (EVM),sig.messageparses to exactly the storedmsgcontent. So legitimate submissions on both paths pass unchanged; only true mismatches are rejected.Testing
tsc --noEmitclean; existinggovernance-apitest suite green.Scope
Independent of #778 (different region of
message.ts); either can merge first.