Transaction Size DoS
Detects unbounded account lists in CPI that can cause transaction size DoS.
Transaction Size DoS
Overview
The transaction size DoS detector identifies unbounded account list iteration in CPI calls that can exceed Solana’s 1232-byte transaction size limit. Each account in a transaction consumes 32 bytes (pubkey) plus metadata, so exceeding roughly 30-35 accounts can cause transaction failures that attackers can exploit for denial-of-service.
For remediation guidance, see Transaction Size DoS Remediation.
Why This Is an Issue
Solana transactions are limited to 1232 bytes. Programs that construct CPI calls with dynamically-sized account lists controlled by user input can create transactions that exceed this limit. Attackers can exploit this by providing excessive account lists to force transaction failures, causing denial-of-service for legitimate users and wasting their transaction fees.
How to Resolve
Before (Vulnerable)
// Vulnerable: CPI with unbounded account list
pub fn process_batch(ctx: Context<Batch>, account_keys: Vec<Pubkey>) -> Result<()> {
let mut accounts = Vec::new();
for key in account_keys.iter() { // No upper bound
accounts.push(AccountMeta::new(*key, false));
}
invoke(&instruction, &accounts)?;
Ok(())
}
After (Fixed)
const MAX_ACCOUNTS: usize = 20;
pub fn process_batch(ctx: Context<Batch>, account_keys: Vec<Pubkey>) -> Result<()> {
require!(account_keys.len() <= MAX_ACCOUNTS, ErrorCode::TooManyAccounts);
let mut accounts = Vec::with_capacity(account_keys.len());
for key in account_keys.iter() {
accounts.push(AccountMeta::new(*key, false));
}
invoke(&instruction, &accounts)?;
Ok(())
}
Example JSON Finding
{
"detector": "transaction-size-dos",
"severity": "medium",
"confidence": 0.6,
"message": "CPI call with dynamically-sized account list without upper bound validation",
"location": { "function": "process_batch", "block": 1, "statement": 4 }
}
Detection Methodology
- CPI account list analysis: Identifies CPI calls where the account list is built dynamically from user input.
- Bounds checking: Verifies that dynamically-constructed account lists have maximum size validation.
- Loop-CPI pattern: Detects CPI calls inside loops without account count limits.
- User-controlled count: Tracks whether the account count derives from instruction data.
Limitations
False positives: Programs with small constant-size account lists may be flagged if the constant is not visible at bytecode level. False negatives: Transaction size issues caused by large instruction data rather than account counts are not detected.
Related Detectors
- DoS Compute Exhaustion — compute-based denial-of-service
- CPI In-Loop DoS — CPI calls in loops