Hardcoded Sysvar Address
Detects hardcoded sysvar addresses instead of using proper sysvar::id() derivation functions.
Hardcoded Sysvar Address
Overview
Remediation Guide: How to Fix Hardcoded Sysvar Addresses
The hardcoded sysvar address detector identifies Solana programs that validate sysvar accounts (Clock, Rent, Stake History, Instructions, EpochSchedule, etc.) against hardcoded byte arrays instead of using the proper sysvar::id() derivation functions. While the hardcoded addresses are functionally correct (sysvar addresses are stable), using derivation functions improves code readability, reduces copy-paste errors, and follows Solana development best practices.
Sigvex scans CheckKey statements for constants that match known sysvar address bytes (Clock, Rent, Stake History, Instructions, EpochSchedule, Recent Blockhashes, Slot Hashes, Slot History, Fees). Matches generate low-severity findings recommending the corresponding sysvar::id() function. 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:
sysvar::clock::id()is self-documenting; a 32-byte array is not. - Copy-paste risk: Manually copying sysvar addresses between files or projects risks transcription errors that produce subtle, hard-to-diagnose bugs.
- Maintenance: If a developer needs to change which sysvar is checked, finding and replacing a raw byte array is error-prone compared to changing a function call.
- Consistency: Mixing derivation functions and hardcoded addresses in the same codebase creates inconsistency.
How to Resolve
Native Rust
use solana_program::{account_info::AccountInfo, entrypoint::ProgramResult, sysvar};
pub fn validate_clock(accounts: &[AccountInfo]) -> ProgramResult {
let clock_account = &accounts[0];
// Instead of: if *clock_account.key != Pubkey::from([6, 167, 213, ...]) {
if *clock_account.key != sysvar::clock::id() {
return Err(ProgramError::InvalidAccountData);
}
Ok(())
}
Anchor
#[derive(Accounts)]
pub struct ValidateClock<'info> {
pub clock: Sysvar<'info, Clock>, // Handles validation automatically
}
Examples
Vulnerable Code
use solana_program::{account_info::AccountInfo, entrypoint::ProgramResult, pubkey::Pubkey};
// Hardcoded Clock sysvar address
const CLOCK_SYSVAR: [u8; 32] = [
6, 167, 213, 23, 24, 199, 116, 201, 40, 86, 99, 152, 105, 29, 94, 182,
139, 94, 184, 163, 155, 75, 109, 92, 115, 85, 91, 33, 0, 0, 0, 0,
];
pub fn check_time(accounts: &[AccountInfo]) -> ProgramResult {
let clock = &accounts[0];
if *clock.key != Pubkey::from(CLOCK_SYSVAR) {
return Err(ProgramError::InvalidAccountData);
}
Ok(())
}
Fixed Code
use solana_program::{account_info::AccountInfo, entrypoint::ProgramResult, sysvar};
pub fn check_time(accounts: &[AccountInfo]) -> ProgramResult {
let clock = &accounts[0];
if *clock.key != sysvar::clock::id() {
return Err(ProgramError::InvalidAccountData);
}
Ok(())
}
Sample Sigvex Output
{
"detector_id": "hardcoded-sysvar-address",
"severity": "low",
"confidence": 0.70,
"description": "The program uses a hardcoded address for the Clock sysvar instead of deriving it using the proper ID function. Using the derivation function ensures compatibility and follows Solana best practices.",
"location": { "function": "check_time", "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 sysvar matching: The extracted bytes are compared against a table of known sysvar addresses (Clock, Rent, Stake History, Instructions, EpochSchedule, Recent Blockhashes, Slot Hashes, Slot History, Fees).
- Finding generation: Matches generate a low-severity finding with the specific sysvar name and recommended replacement function.
Context modifiers:
- Anchor programs: confidence reduced (Anchor uses typed sysvar accounts)
- Admin/initialization functions: confidence reduced by 40%
Limitations
False positives:
- Constants that coincidentally match sysvar address bytes but are used for a different purpose will be flagged. This is unlikely given the specificity of 32-byte addresses.
False negatives:
- Sysvar addresses stored in non-constant expressions (e.g., loaded from config accounts) are not detected.
- Addresses compared through non-
CheckKeypatterns (e.g., manual byte comparison in a loop) are not detected.
Related Detectors
- Hardcoded System Program Address — same pattern for system program addresses
- Sysvar Substitution — detects missing sysvar validation entirely