Skip to main content
Sigvex

Hardcoded System Program Address Remediation

How to fix hardcoded system program addresses by using named constants.

Remediating Hardcoded System Program Addresses

Overview

Related Detector: Hardcoded System Program Address

Hardcoded system program addresses as byte arrays reduce readability and increase the risk of copy-paste errors. The fix is to replace raw byte arrays with the canonical named constants from the Solana SDK or SPL libraries.

Before (Vulnerable)

use solana_program::{account_info::AccountInfo, entrypoint::ProgramResult, pubkey::Pubkey};

const SYSTEM_PROGRAM: [u8; 32] = [0u8; 32]; // System program address

pub fn create_account(accounts: &[AccountInfo]) -> ProgramResult {
    if *accounts[0].key != Pubkey::from(SYSTEM_PROGRAM) {
        return Err(ProgramError::IncorrectProgramId);
    }
    Ok(())
}

After (Fixed)

use solana_program::{account_info::AccountInfo, entrypoint::ProgramResult, system_program};

pub fn create_account(accounts: &[AccountInfo]) -> ProgramResult {
    if *accounts[0].key != system_program::id() {
        return Err(ProgramError::IncorrectProgramId);
    }
    Ok(())
}

Alternative Mitigations

  1. Anchor Program type: Use Program<'info, System> or Program<'info, Token> for automatic program ID validation.
#[derive(Accounts)]
pub struct CreateAccount<'info> {
    pub system_program: Program<'info, System>,
}
  1. Centralized constants: If you need to support multiple program versions or cannot use the SDK constants directly, create a centralized constants module with clear naming.
pub mod program_ids {
    use solana_program::pubkey::Pubkey;
    pub const TOKEN_PROGRAM: Pubkey = spl_token::id();
    pub const TOKEN_2022_PROGRAM: Pubkey = spl_token_2022::id();
}
  1. Compile-time validation: Use const assertions to verify that any locally-defined constants match the canonical SDK values.

Common Mistakes

  • Replacing the constant but keeping the old use import: Clean up unused imports after switching to the SDK constant.
  • Using system_program::id() instead of system_program::ID: Both work, but ID is a Pubkey constant while id() returns a Pubkey. For CheckKey comparisons, either is fine.
  • Mixing canonical and hardcoded addresses: Replace all instances in the codebase, not just the flagged one. Grep for 32-byte array patterns.
  • Forgetting third-party programs: the standard NFT metadata program and other ecosystem programs also have canonical constants in their respective crate libraries.

References