Skip to main content
Sigvex

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 the account-validation framework’s max_len attribute for compile-time safety.

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.

References