fix(uexecutor): cap the outbound gateway payload at admission (F-2026-18146) - #364
Merged
Merged
Conversation
BuildOutboundsFromReceipt copied an attacker-controlled payload into state unbounded. Rejecting there reverts the whole EVM tx, so the gateway burn rolls back with it.
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.
F-2026-18146. Both halves the auditor asked for: admission rejects the oversized payload, and the poll survives one anyway.
Core: cap the payload at admission
MaxOutboundPayloadBytes(128 KiB) enforced onevent.Payloadincreate_outbound.go. The gateway payload is attacker-controlled and lands in state unbounded today.MaxUniversalPayloadByteson purpose. Same number, different reason: geth's txpool rejects a transaction over 128 KB, so a larger payload is unsendable once TSS has signed it.Client: survive a page that does not fit
ResourceExhaustedthe client now halves the page and retries the same offset. Every other error still fails the poll.The cap is what makes the client side clean: halving terminates because a page of one is at most 128 KiB against an 8 MiB receive limit, so no row is ever unfetchable and nothing is skipped. A page of one that still fails is returned as a real error.
Static page sizing was the alternative and is worse: 8 MiB over a 128 KiB cap is 64 rows a page, so 320 rows a poll instead of 5000, or 78 round trips to hold today's throughput. That trades this finding for the starvation fixed in F-2026-18817, and pays on every poll for a case the cap should now prevent.
Tests