Skip to main content
Sigvex

Non-Anchor Discriminator Remediation

How to fix missing instruction discrimination in non-an account-validation framework programs.

Non-Anchor Discriminator Remediation

Overview

Related Detector: Non-Anchor Discriminator

Missing instruction discrimination allows instruction confusion attacks. The fix is to implement explicit instruction routing using the first byte(s) of instruction data as a discriminator, with a default error case for unknown instructions.

pub fn process_instruction(
    program_id: &Pubkey,
    accounts: &[AccountInfo],
    data: &[u8],
) -> ProgramResult {
    let (discriminator, rest) = data.split_first()
        .ok_or(ProgramError::InvalidInstructionData)?;
    match discriminator {
        0 => initialize(program_id, accounts, rest),
        1 => deposit(program_id, accounts, rest),
        2 => withdraw(program_id, accounts, rest),
        _ => Err(ProgramError::InvalidInstructionData),
    }
}

Alternative Mitigations

Borsh Enum Instruction Routing

Use Borsh-serialized instruction enums for type-safe routing:

#[derive(BorshDeserialize)]
pub enum Instruction {
    Initialize { param: u64 },
    Deposit { amount: u64 },
    Withdraw { amount: u64 },
}

let instruction = Instruction::try_from_slice(data)?;
match instruction {
    Instruction::Initialize { param } => initialize(accounts, param),
    Instruction::Deposit { amount } => deposit(accounts, amount),
    Instruction::Withdraw { amount } => withdraw(accounts, amount),
}

Common Mistakes

Mistake: Falling Through to Default Handler

// WRONG: unknown instructions processed by deposit handler
match tag {
    0 => initialize(accounts),
    _ => deposit(accounts, data),  // Catch-all is dangerous
}

Always return an error for unknown discriminator values.

References