PDA Ownership Validation Remediation
How to fix PDA usage without ownership validation.
PDA Ownership Validation Remediation
Overview
Related Detector: PDA Ownership Validation
PDA ownership vulnerabilities allow attackers to substitute accounts owned by other programs at expected PDA addresses. The fix is to always verify account.owner == program_id before reading or writing PDA data.
Recommended Fix
Before (Vulnerable)
let vault = &accounts[0]; // No owner check
let data = vault.data.borrow();
After (Fixed)
let vault = &accounts[0];
if vault.owner != program_id {
return Err(ProgramError::IllegalOwner);
}
let data = vault.data.borrow();
Alternative Mitigations
1. Anchor Account type
#[account(seeds = [b"vault"], bump)]
pub vault: Account<'info, Vault>, // Owner validated automatically
2. Combined address and owner check
let (expected_pda, _) = Pubkey::find_program_address(&[b"vault"], program_id);
if vault.key != &expected_pda || vault.owner != program_id {
return Err(ProgramError::InvalidAccountData);
}
Common Mistakes
Mistake 1: Checking address but not owner
// INSUFFICIENT: correct address but wrong owner
if vault.key != &expected_pda { return Err(...); }
// Missing: vault.owner check
Mistake 2: Using UncheckedAccount in Anchor without manual validation
// WRONG: UncheckedAccount skips owner validation
pub vault: UncheckedAccount<'info>,
// Must add: #[account(constraint = vault.owner == program_id)]