Missing token account constraints leads to potential mint confusion and unauthorized token transfers
ProcessWithdrawal token accounts lack ownership and mint constraints, enabling confusion attacks where attackers manipulate inputs to bypass mint restrictions.
Description
The ProcessWithdrawal instruction context fails to validate critical properties of the token accounts used in the withdrawal operation. Specifically, vault_token_account and recipient_token_account lack constraints to verify:
- Vault token account ownership: No validation that
vault_token_accountis owned byvault_authority. - Mint matching: No validation that either token account matches the expected
vault.token_mint.
Current implementation:
#[account(mut)]pub vault_token_account: Account<'info, TokenAccount>,#[account(mut)]pub recipient_token_account: Account<'info, TokenAccount>,
The only validation performed is a runtime check at line 151 that recipient_token_account.owner matches the authorized recipient, but this does not validate the mint or the vault account's ownership.
Impact
Attackers can potentially manipulate token account inputs to withdraw wrong tokens or bypass mint restrictions. While the SPL Token Program provides some protection by verifying authority signatures, the lack of mint and ownership validation creates opportunities for confusion attacks and could allow transfers of unintended token types. This is particularly critical given that vault.token_mint is stored but never enforced, making the entire mint tracking system ineffective.
Recommendation
Add explicit constraints to the vault_token_account and recipient_token_account in ProcessWithdrawal:
// vault_token_account: Add ownership and mint validation#[account(mut,constraint = vault_token_account.owner == vault_authority.key() @ ErrorCode::InvalidVaultAccount,constraint = vault_token_account.mint == vault.token_mint @ ErrorCode::InvalidMint)]pub vault_token_account: Account<'info, TokenAccount>,// recipient_token_account: Add mint validation#[account(mut,constraint = recipient_token_account.mint == vault.token_mint @ ErrorCode::MintMismatch)]pub recipient_token_account: Account<'info, TokenAccount>,
Additionally, ensure vault.token_mint is properly validated during initialization:
#[account(constraint = token_mint.owner == &spl_token::ID @ ErrorCode::InvalidMint)]pub token_mint: Account<'info, Mint>,
Define the new error codes:
#[msg("Token account not owned by vault authority")]InvalidVaultAccount,#[msg("Token mint does not match vault mint")]InvalidMint,#[msg("Recipient token mint does not match vault mint")]MintMismatch,
Resolution
Fair Casino: Fixed.
Zealynx: Verified.

