Hardcoded System Program Address
Detects hardcoded system program addresses instead of using named constants for program IDs.
Hardcoded System Program Address
Overview
Remediation Guide: How to Fix Hardcoded System Program Addresses
The hardcoded system program address detector identifies Solana programs that validate system program IDs (System Program, Token Program, Token-2022 Program, Associated Token Program, Memo Program, BPF Loader Upgradeable, Metaplex Token Metadata) against hardcoded byte arrays instead of using named constants. While the hardcoded addresses are functionally correct (system program addresses are immutable), using named constants improves code readability, prevents copy-paste errors, and follows Solana development best practices.
Sigvex scans CheckKey statements for constants that match known system program address bytes. Matches generate low-severity findings recommending the corresponding named constant. CWE mapping: CWE-1188 (Insecure Default Initialization of Resource).
Why This Is an Issue
This is a code quality issue rather than a security vulnerability:
- Readability:
system_program::id()orspl_token::id()communicates intent clearly; a 32-byte array does not. - Copy-paste risk: System program addresses are 32-byte arrays that differ by only a few bytes. Copying the wrong one produces a validation check against the wrong program, which is a real security bug.
- Cross-program compatibility: Programs that interact with Token-2022 or multiple program versions benefit from using the canonical constants, which are updated with SDK releases.
- Audit efficiency: Auditors reviewing code can quickly verify program ID constants but must manually decode byte arrays.
How to Resolve
Native Rust
use solana_program::{account_info::AccountInfo, entrypoint::ProgramResult, system_program};
pub fn validate_system_program(accounts: &[AccountInfo]) -> ProgramResult {
let sys_program = &accounts[0];
// Instead of: if *sys_program.key != Pubkey::from([0, 0, 0, ...]) {
if *sys_program.key != system_program::id() {
return Err(ProgramError::IncorrectProgramId);
}
Ok(())
}
Anchor
#[derive(Accounts)]
pub struct CreateAccount<'info> {
pub system_program: Program<'info, System>, // Validates automatically
pub token_program: Program<'info, Token>, // Validates automatically
}
Examples
Vulnerable Code
use solana_program::{account_info::AccountInfo, entrypoint::ProgramResult, pubkey::Pubkey};
const TOKEN_PROGRAM: [u8; 32] = [
6, 221, 246, 225, 215, 101, 161, 147, 217, 203, 225, 70, 206, 235, 121, 172,
28, 180, 133, 237, 95, 91, 55, 145, 58, 140, 245, 133, 126, 255, 0, 169,
];
pub fn validate_token(accounts: &[AccountInfo]) -> ProgramResult {
if *accounts[0].key != Pubkey::from(TOKEN_PROGRAM) {
return Err(ProgramError::IncorrectProgramId);
}
Ok(())
}
Fixed Code
use solana_program::{account_info::AccountInfo, entrypoint::ProgramResult};
pub fn validate_token(accounts: &[AccountInfo]) -> ProgramResult {
if *accounts[0].key != spl_token::id() {
return Err(ProgramError::IncorrectProgramId);
}
Ok(())
}
Sample Sigvex Output
{
"detector_id": "hardcoded-system-program-address",
"severity": "low",
"confidence": 0.70,
"description": "The program uses a hardcoded address for Token Program instead of using the proper constant. Using the constant ensures compatibility and follows Solana best practices.",
"location": { "function": "validate_token", "offset": 0 }
}
Detection Methodology
The detector scans all CheckKey statements in the function:
- Constant extraction: For each
CheckKeywith a constant expected value, the detector extracts the byte representation. - Known program matching: The extracted bytes are compared against a table of known system program addresses (System Program, Token Program, Token-2022 Program, Associated Token Program, Memo Program, BPF Loader Upgradeable, Metaplex Token Metadata).
- Finding generation: Matches generate a low-severity finding with the specific program name and recommended replacement constant.
Context modifiers:
- Anchor programs: confidence reduced (Anchor uses typed program accounts)
- Admin/initialization functions: confidence reduced by 40%
Limitations
False positives:
- Constants that coincidentally match program address bytes but serve a different purpose will be flagged. Given the specificity of 32-byte addresses, this is unlikely.
False negatives:
- Program addresses stored in non-constant expressions (e.g., loaded from config accounts) are not detected.
- Custom or third-party program addresses (beyond the seven well-known programs tracked) are not flagged.
Related Detectors
- Hardcoded Sysvar Address — same pattern for sysvar addresses
- CPI Program Validation — detects missing program validation in CPI calls