Skip to main content
Sigvex

Remediating Input Validation

How to validate user-controlled instruction data and account fields in Solana programs.

Remediating Input Validation

Overview

Related Detector: Input Validation

All instruction data and account fields must be validated before use in security-critical operations. This includes bounds checking amounts, validating array indices, and verifying pubkey parameters.

Before (Vulnerable)

pub fn transfer(accounts: &[AccountInfo], amount: u64) -> ProgramResult {
    let source = &accounts[0];
    let dest = &accounts[1];
    // No validation — amount could exceed balance
    **source.lamports.borrow_mut() -= amount;
    **dest.lamports.borrow_mut() += amount;
    Ok(())
}

After (Fixed)

pub fn transfer(accounts: &[AccountInfo], amount: u64) -> ProgramResult {
    let source = &accounts[0];
    let dest = &accounts[1];

    if amount == 0 {
        return Err(ProgramError::InvalidArgument);
    }
    if amount > source.lamports() {
        return Err(ProgramError::InsufficientFunds);
    }

    **source.lamports.borrow_mut() -= amount;
    **dest.lamports.borrow_mut() += amount;
    Ok(())
}

Alternative Mitigations

  • an account-validation framework constraints: Use #[account(constraint = amount > 0)] for declarative validation.
  • Borsh with bounds: Implement custom BorshDeserialize that validates ranges during deserialization.

Common Mistakes

  • Validating only one bound: Checking amount > 0 but not amount <= balance.
  • Trusting account data without owner check: Validating instruction data but not verifying that account data comes from a trusted program.

References