Skip to content

fix: sync message signing — bind accounts, vault index, split discriminators#32

Open
0xLeo-sqds wants to merge 2 commits intofeat/resolved-signerfrom
messages-remediation
Open

fix: sync message signing — bind accounts, vault index, split discriminators#32
0xLeo-sqds wants to merge 2 commits intofeat/resolved-signerfrom
messages-remediation

Conversation

@0xLeo-sqds
Copy link
Copy Markdown
Collaborator

Summary

Fixes three vulnerabilities in the sync transaction message signing path identified during audit review.

1. Remaining accounts not committed in signed message

External signers sign a hash that includes the instruction payload but not the account table those instructions operate on. A relayer who obtains valid signatures could swap remaining_accounts (e.g. replace a destination token account) while reusing the same signatures, redirecting funds.

Fix: hash each remaining account's pubkey and is_writable flag into the signed message.

2. account_index not committed in signed message

account_index determines which vault PDA gets signer authority for CPIs. It was passed as an instruction arg but never entered the signed hash. A relayer could change it to make a different vault sign.

Fix: include account_index as a byte in the signed message.

3. Shared discriminator between sync_transaction and sync_settings_transaction

Both used "squads-sync" as the message prefix. A signature for one could theoretically replay against the other if the payload bytes happen to deserialize under both interpretations.

Fix: split into three distinct slugs:

  • "sync_transaction_v2" — for sync_transaction_v2
  • "sync_transaction_legacy" — for legacy sync transactions
  • "sync_settings_tx_v2" — for sync settings transactions

Scope

All three fixes are sync-path only. Async transactions store accounts on-chain and go through proposal/vote governance, so they're not affected.

Also removed dead code: the unused create_signature_message function.

Files changed

Program:

  • messages.rs — replaced create_sync_consensus_message with 3 new functions, deleted dead create_signature_message
  • transaction_execute_sync.rs — passes account_index + execution accounts to new message fn
  • transaction_execute_sync_legacy.rs — same, with sysvar offset computation
  • settings_transaction_sync.rs — uses new settings-specific message fn

Tests:

  • externalSignerSecurity.ts — updated sync message builder
  • externalSignerNoncePersistence.ts — updated sync message builder
  • mixedSignerSync.ts — updated inline message construction

Test plan

  • Full V2 test suite: 189 passing, 1 expected failure (increment_account_index)
  • mixedSignerSync (5 mixed signers, precompile + syscall): passing
  • externalSignerSecurity (6 attack scenario tests): passing
  • externalSignerNoncePersistence (6 nonce tests): passing

…nique discriminators

Addresses three sync-path vulnerabilities:
1. remaining_accounts now included in signed hash (prevents account swap)
2. account_index now included in signed hash (prevents vault swap)
3. Split 'squads-sync' into 'sync_transaction_v2', 'sync_transaction_legacy',
   and 'sync_settings_tx_v2' (prevents cross-instruction replay)
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