Skip to content

fix: F-2026-18184 | [Dual Defense] Empty SVM CEA Recipient Encodes to Invalid Address and Strands Outbound - #341

Merged
0xNilesh merged 4 commits into
audit-fixesfrom
F-2026-18184
Aug 26, 2026
Merged

fix: F-2026-18184 | [Dual Defense] Empty SVM CEA Recipient Encodes to Invalid Address and Strands Outbound#341
0xNilesh merged 4 commits into
audit-fixesfrom
F-2026-18184

Conversation

@0xNilesh

@0xNilesh 0xNilesh commented Aug 26, 2026

Copy link
Copy Markdown
Member

An empty recipient is the gateway's sentinel for parking funds in the caller's CEA. Core hex-encodes the raw event bytes, so it reaches the SVM builder as "0x", which was rejected pre-sign. The outbound sat PENDING with the PRC20 already burned.

The fix is to do what the user asked for, not to abort.

What changed

  • universalClient/chains/svm/tx_builder.go only. All three recipient parses go through one resolveRecipient.
  • The sentinel resolves to the sender's CEA via ["push_identity", sender], the derivation this file already uses for cea_authority. The gateway short-circuits its withdraw when recipient == CEA, since finalize has already staged vault to CEA.
  • Signing and build paths share the helper, so the pubkey in the TSS message matches the accounts list.
  • Honoured on withdraw (id 1) only. Execute, revert, rescue and the ref route reject it.
  • No core or EVM change.

Rollout

All UVs must be upgraded before a parked outbound can sign. A mixed fleet leaves un-upgraded UVs rejecting "0x" while upgraded ones sign, which can hold the signing set below quorum.

Tests

  • Equivalence against the pre-change parser across 10 recipient forms, so nothing that resolves today changes.
  • Frozen signing hashes for the parked and ordinary paths.
  • Devnet simulation: a parked and an ordinary withdraw reach the same on-chain stage, past the program's seeds constraint on cea_authority.
  • Per-instruction-id scoping, and a full build asserting the CEA lands in both the cea_authority and recipient slots.
  • Mutation: 4 run, 4 caught.

Simulations are now gated on RUN_SVM_SIM=1 instead of a hard skip, matching develop. They need the dummy gateway's TSS PDA set to 0xc681e7bdacfe4dc7209a15ff052f897c3d87008f; it currently holds a different key, so they fail on TSS auth on every branch including develop.

Fixes F-2026-18184.

0xNilesh and others added 3 commits August 26, 2026 17:39
Honours the gateway's bytes("") parking convention on withdraw instead of rejecting "0x" pre-sign, which stranded the outbound PENDING with the PRC20 already burned. F-2026-18184.
Keeps both sides: #338's removal of the recipient-ATA create and its
NoRecipientATACreate test, plus this branch's parked-recipient sentinel
resolution and tests.
@0xNilesh
0xNilesh merged commit 2b07bcc into audit-fixes Aug 26, 2026
3 of 4 checks passed
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