diff --git a/program-tests/compressed-token-test/tests/light_token/create.rs b/program-tests/compressed-token-test/tests/light_token/create.rs index 85e8773386..a9f9aa5296 100644 --- a/program-tests/compressed-token-test/tests/light_token/create.rs +++ b/program-tests/compressed-token-test/tests/light_token/create.rs @@ -694,4 +694,29 @@ async fn test_create_compressible_token_account_failing() { // Only version 3 (ShaFlat) is supported for compressible accounts light_program_test::utils::assert::assert_rpc_error(result, 0, 2).unwrap(); } + + // Test 13: Rent sponsor self-referencing token account (audit issue #9) + // The rent sponsor cannot be the same account as the token account being created. + // This would create a self-referencing loop that could corrupt account state. + // Error: 3 (InvalidAccountData) + { + context.token_account_keypair = Keypair::new(); + let compressible_data = CompressibleData { + compression_authority: context.compression_authority, + rent_sponsor: context.token_account_keypair.pubkey(), // Self-reference! + num_prepaid_epochs: 2, + lamports_per_write: Some(100), + account_version: light_token_interface::state::TokenDataVersion::ShaFlat, + compress_to_pubkey: false, + payer: payer_pubkey, + }; + + create_and_assert_token_account_fails( + &mut context, + compressible_data, + "rent_sponsor_self_reference", + 3, // InvalidAccountData + ) + .await; + } } 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..4c549b41a1 100644 --- a/programs/compressed-token/program/src/shared/initialize_ctoken_account.rs +++ b/programs/compressed-token/program/src/shared/initialize_ctoken_account.rs @@ -69,6 +69,12 @@ pub fn create_compressible_account<'info>( account_seeds: Option<&[Seed]>, is_ata: bool, ) -> Result, ProgramError> { + // Validate rent payer is not the token account itself + if rent_payer.key() == target_account.key() { + msg!("Rent sponsor cannot be the token account itself"); + return Err(ProgramError::InvalidAccountData); + } + // Validate rent_payment != 1 (epoch boundary edge case) if compressible_config.rent_payment == 1 { msg!("Prefunding for exactly 1 epoch is not allowed. If the account is created near an epoch boundary, it could become immediately compressible. Use 0 or 2+ epochs.");