- Category: unsafe_patterns
- Severity: Medium
- Rule name:
unsafe_pattern
S006 is the catch-all for potentially unsafe language or runtime patterns that don't have a more specific code. The flagship case is timestamp-as-randomness: using env.ledger().timestamp() as entropy. The detector fires when env.ledger().timestamp() appears inside:
- a function whose name contains
rand,seed,pick, orwinner, or - a variable binding whose name contains one of those tokens.
Other unsafe runtime patterns surface under the same category, each with a suggested safe alternative.
A block timestamp is not secret entropy. Validators can nudge env.ledger().timestamp() within a small window, so any "random" outcome derived from it — a lottery winner, a shuffled order, a seed — is predictable and manipulable. An attacker who can influence or predict the value can guarantee favorable outcomes and replay the exploit.
#![no_std]
use soroban_sdk::{contract, contractimpl, Env, Vec, Address};
#[contract]
pub struct Lottery;
#[contractimpl]
impl Lottery {
pub fn pick_winner(env: Env, entrants: Vec<Address>) -> Address {
// S006: timestamp used as the randomness source for the winner.
let seed = env.ledger().timestamp();
let index = (seed % entrants.len() as u64) as u32;
entrants.get(index).unwrap()
}
}#![no_std]
use soroban_sdk::{contract, contractimpl, Env, Vec, Address};
#[contract]
pub struct Lottery;
#[contractimpl]
impl Lottery {
pub fn pick_winner(env: Env, entrants: Vec<Address>) -> Address {
// Use the host PRNG, which is seeded from unpredictable entropy.
let len = entrants.len();
let index = env.prng().gen_range(0..len as u64) as u32;
entrants.get(index).unwrap()
}
}- Vector:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N - Base score: 7.5
- Rating: High
When the pattern is exploitable randomness, a low-complexity attacker can bias outcomes (high integrity impact), so the realized risk is high even though the catalog severity for the broad category is Medium.
- Never use
env.ledger().timestamp()(or sequence number) as a sole source of randomness. - Use the Soroban host PRNG (
env.prng()), seeded from a fresh entropy source. - For high-value randomness, use a VRF oracle or commit-reveal scheme combining multiple unpredictable inputs.
- For other flagged patterns, apply the suggested safe alternative or add an explicit safety check.