Skip to content

Latest commit

 

History

History
96 lines (78 loc) · 5.67 KB

File metadata and controls

96 lines (78 loc) · 5.67 KB

Sanctifier Error Code Mapping

Sanctifier now uses a unified finding code system across sanctifier-core and sanctifier-cli outputs.

Each code emitted by a detector links to its full page in the Detector Catalog — what it catches, a vulnerable example, the fix, and references.

Code Category Meaning Detector page
S001 authentication Missing authentication guard in a state-mutating function auth_gap
S002 panic_handling panic! / unwrap / expect usage that may abort execution panic_detection
S003 arithmetic Unchecked arithmetic with overflow/underflow risk arithmetic_overflow
S004 storage_limits Ledger entry size exceeds or approaches configured limits ledger_size
S005 storage_keys Potential storage key collision
S006 storage_durability Persistent/instance storage access without a TTL extension missing_ttl
S007 custom_rule User-defined custom rule match
S009 logic A Result that is silently dropped unhandled_result
S012 code_hygiene Hardcoded admin address / secret literal in an auth context hardcoded_addr
S013 code_hygiene transfer/mint/burn missing amount > 0 / from != to guards edge_amount
S015 code_hygiene Unused local binding (dead code) unused_variable
S016 code_hygiene Duplicate/inconsistent #[contracterror] discriminants error_code_collision
S017 arithmetic Fee/interest integer division that rounds to zero for micro-amounts fee_rounding
SANCT_ARG_DOS denial_of_service Vec/Map argument iterated without a length cap arg_dos
SANCT_UNWRAP panic_handling unwrap / expect / risky unwrap_or_default inside #[contractimpl] entrypoints; replace with typed errors or explicit domain defaults sanct_unwrap
SANCT_VISIBILITY authentication Helper-shaped state mutator exposed through #[contractimpl] without authorization sanct_visibility
SANCT_UNBOUNDED_STORAGE denial_of_service Persistent/instance collection grows via append/insert with no removal or length cap unbounded_storage
SANCT_UNBOUNDED_RETURN scalability Public entrypoint returning an unbounded collection (Vec or Map) unbounded_return
SANCT_EAGER_UNWRAP_OR gas_efficiency Eagerly-computed expensive fallback in unwrap_or() wastes gas eager_unwrap_or
SANCT_CONTRACTERROR_ENUM logic Public function returns error enum missing #[contracterror] or repr contracterror_enum
SANCT_PROOF_LENGTH_UNVALIDATED zk_verification Proof/public-input byte array reaches a verifier call with no length check first proof_length_check
SANCT_VK_PROVENANCE cryptography ZK verifying key accepted at runtime and stored with no auth/hash-pin guard vk_provenance

Full catalog: Detector Catalog →

Source-optional (compiled WASM) codes

Emitted only by sanctifier wasm, which analyzes a deployed module directly. See Source-Optional WASM Analysis for the full source-vs-WASM comparison.

Code Category Meaning
W001 wasm Compiled module has no Soroban contract spec section; may not be a Soroban contract
W002 wasm Compiled module exports no callable functions
W003 wasm Compiled module is missing Soroban environment metadata (interface version)
W004 wasm Compiled module uses floating-point value types, which the Soroban host rejects

Detector catalog

SANCT_UNWRAP

Flags unwrap(), expect(..), and risky unwrap_or_default() calls inside Soroban #[contractimpl] entrypoints. In an entrypoint, an attacker-triggered missing value can abort the whole transaction or silently turn absent financial state into a default value.

#[contractimpl]
impl Token {
    pub fn balance(env: Env, id: Address) -> i128 {
        env.storage().persistent().get(&DataKey::Balance(id)).unwrap_or_default()
    }
}

Prefer explicit handling: return a typed Result, map missing state to a domain-specific Error, or use an explicit default such as unwrap_or(0) only when zero is the intended contract state.

SANCT_VISIBILITY

Flags public helper-shaped methods inside #[contractimpl] that mutate contract state without calling require_auth() or require_auth_for_args(). Leading underscores and explicit helper or internal naming are treated as evidence that a method was intended for internal use.

#[contractimpl]
impl Token {
    pub fn _set_balance(env: Env, owner: Address, amount: i128) {
        write_balance(&env, &owner, amount);
    }
}

Keep helpers private when possible. If a helper is intentionally exposed as a contract entrypoint, authenticate the appropriate principal before any state mutation.

Where codes appear

  • Text output from sanctifier analyze
  • JSON report output under:
    • error_codes (full mapping table)
    • each item inside findings.* as code