Account Type Confusion
Detects accounts used in conflicting roles or deserialized as the wrong type, enabling attackers to substitute one account type for another.
Account Type Confusion
Overview
Remediation Guide: How to Fix Account Type Confusion
The account type confusion detector identifies Solana programs that use the same account in conflicting roles (e.g., as both a token account and a program configuration account) or that deserialize account data without verifying the account’s discriminator or owner. Without type validation, an attacker can pass a crafted account with the correct data layout but wrong semantics, tricking the program into operating on spoofed data.
Why This Is an Issue
Solana accounts are untyped byte arrays. Programs must implement their own type system by checking discriminators (type tags) and owner programs. An account created by Program A with the same data layout as one expected by Program B can be substituted if Program B does not check the owner. The type cosplay attack exploits this to substitute fake vault data, spoofed price feed data, or forged configuration accounts.
How to Resolve
// Before: Vulnerable — no type check
pub fn process(accounts: &[AccountInfo]) -> ProgramResult {
let config = &accounts[0];
let data = config.data.borrow();
let settings: Settings = Settings::try_from_slice(&data)?; // No discriminator check
// Attacker can pass ANY account with matching byte layout
Ok(())
}
// After: Fixed — check discriminator and owner
pub fn process(accounts: &[AccountInfo]) -> ProgramResult {
let config = &accounts[0];
if config.owner != &crate::ID {
return Err(ProgramError::IncorrectProgramId);
}
let data = config.data.borrow();
if data[0..8] != Settings::DISCRIMINATOR {
return Err(ProgramError::InvalidAccountData);
}
let settings = Settings::try_from_slice(&data[8..])?;
Ok(())
}
Detection Methodology
- Deserialization tracking: Identifies account data reads (
borrow(),try_from_slice) without preceding owner or discriminator checks. - Role conflict detection: Tracks each account index across the function to determine if it is used in multiple incompatible contexts (e.g., as both a source and destination of funds).
- Owner check detection: Searches for
account.owner == &program_idcomparisons before data access. - Discriminator check detection: Searches for byte-level comparisons on the first 8 bytes of account data.
Limitations
False positives: Anchor programs automatically verify discriminators; bytecode-level detection may not recognize this. False negatives: Custom discriminator formats not matching the 8-byte standard may be missed.
Related Detectors
- Type Cosplay — detects account type substitution attacks
- Missing Owner Check — detects missing owner validation