From a7e3210952ecf2fa66e9d1ddd8da97786fe1f182 Mon Sep 17 00:00:00 2001 From: ananas-block Date: Fri, 6 Feb 2026 08:01:15 +0100 Subject: [PATCH 1/2] fix: zero base token bytes before init to prevent IDL buffer attack Audit issue #17 (CRITICAL): Token::new_zero_copy only sets mint, owner, and state fields without zeroing amount, delegate, delegated_amount, is_native, or close_authority. An attacker could pre-set the amount field via IDL buffer. Zero all 165 base token bytes before initialization. --- .../program/src/shared/initialize_ctoken_account.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/programs/compressed-token/program/src/shared/initialize_ctoken_account.rs b/programs/compressed-token/program/src/shared/initialize_ctoken_account.rs index fb802be477..8599a9afa2 100644 --- a/programs/compressed-token/program/src/shared/initialize_ctoken_account.rs +++ b/programs/compressed-token/program/src/shared/initialize_ctoken_account.rs @@ -207,6 +207,13 @@ pub fn initialize_ctoken_account( // Access the token account data as mutable bytes let mut token_account_data = AccountInfoTrait::try_borrow_mut_data(token_account_info)?; + // Zero all base token bytes before initialization to prevent pre-set values + // (e.g., amount field via IDL buffer) from persisting through new_zero_copy, + // which only sets mint, owner, and state without zeroing other fields. + if token_account_data.len() >= 165 { + token_account_data[..165].fill(0); + } + // Use new_zero_copy to initialize the token account // This sets mint, owner, state, account_type, and extensions let (mut ctoken, _) = From 90ddfaa2e58f1c0070395680bb2825af851182e1 Mon Sep 17 00:00:00 2001 From: ananas-block Date: Mon, 9 Feb 2026 05:59:59 +0100 Subject: [PATCH 2/2] fix: fail explicitly when token account data < 165 bytes --- .../program/src/shared/initialize_ctoken_account.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/programs/compressed-token/program/src/shared/initialize_ctoken_account.rs b/programs/compressed-token/program/src/shared/initialize_ctoken_account.rs index 8599a9afa2..120ec45efc 100644 --- a/programs/compressed-token/program/src/shared/initialize_ctoken_account.rs +++ b/programs/compressed-token/program/src/shared/initialize_ctoken_account.rs @@ -210,9 +210,11 @@ pub fn initialize_ctoken_account( // Zero all base token bytes before initialization to prevent pre-set values // (e.g., amount field via IDL buffer) from persisting through new_zero_copy, // which only sets mint, owner, and state without zeroing other fields. - if token_account_data.len() >= 165 { - token_account_data[..165].fill(0); + if token_account_data.len() < 165 { + msg!("Token account data too small: {}", token_account_data.len()); + return Err(ProgramError::InvalidAccountData); } + token_account_data[..165].fill(0); // Use new_zero_copy to initialize the token account // This sets mint, owner, state, account_type, and extensions