Borsh Length DoS Remediation
How to fix unbounded Borsh length prefix DoS vulnerabilities.
Borsh Length DoS Remediation
Overview
Related Detector: Borsh Length DoS
Unbounded Borsh length prefixes enable compute budget exhaustion. The fix is to validate the length prefix against a maximum bound before deserialization and to use Anchor’s max_len attribute for compile-time safety.
Recommended Fix
Before (Vulnerable)
let items: Vec<Item> = BorshDeserialize::deserialize(&mut &data[..])?;
After (Fixed)
const MAX_ITEMS: usize = 100;
let len = u32::from_le_bytes(data[0..4].try_into()?) as usize;
require!(len <= MAX_ITEMS, ErrorCode::TooManyItems);
let items: Vec<Item> = BorshDeserialize::deserialize(&mut &data[..])?;
Alternative Mitigations
Anchor max_len
#[account]
#[derive(InitSpace)]
pub struct MyData {
#[max_len(100)]
pub items: Vec<Item>,
}
Common Mistakes
Mistake: Checking After Deserialization
// WRONG: allocation already happened
let items: Vec<Item> = BorshDeserialize::deserialize(&mut &data[..])?;
require!(items.len() <= MAX_ITEMS, TooMany);
Check the length prefix bytes before calling deserialize.