This page collects the most frequently asked questions about Sanctifier, covering everything from first-run issues to advanced formal verification workflows. Questions are grouped by topic; a glossary of key terms appears at the bottom. If your question involves a specific CLI flag, the authoritative source is alwaysDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/Centurylong/sanctifier/llms.txt
Use this file to discover all available pages before exploring further.
sanctifier <command> --help or the CLI Reference.
General
What is the difference between sanctifier analyze and sanctifier verify?
What is the difference between sanctifier analyze and sanctifier verify?
sanctifier analyze performs static analysis — it parses your Rust source files and matches patterns against a library of known vulnerability signatures (the built-in CVE database plus any [[custom_rules]] in .sanctify.toml). It catches whole classes of bugs such as missing require_auth, unsafe arithmetic, unhandled Result values, and oversized ledger entries. It runs quickly and requires no special toolchain beyond a Rust installation.sanctifier verify performs formal invariant checking — it scans for #[sanctify::invariant(...)] annotations across your codebase and attempts to prove or refute each one using the Z3 SMT solver. Pure-function invariants are dispatched directly to Z3; complex ones involving Soroban host types are reported as KANI ↗ with a reminder to run cargo kani.Run both for maximum coverage:Is Sanctifier a replacement for a professional audit?
Is Sanctifier a replacement for a professional audit?
Does Sanctifier modify my contracts?
Does Sanctifier modify my contracts?
.sanctify.toml configuration file.What are the SOB and SOL CVE ID prefixes?
What are the SOB and SOL CVE ID prefixes?
SOB-YYYY-NNN— Soroban-specific issues: DeFi math bugs, reentrancy patterns, flash loan vulnerabilities, oracle manipulation, and anything tightly coupled to the Soroban execution model.SOL-YYYY-NNN— Stellar/broader platform issues: authorization gaps on token operations, storage TTL problems, hardcoded admin keys, and initialization patterns that affect any Soroban contract.
NNN is a zero-padded sequential number within that year. Examples: SOL-2024-001 (Unprotected Initialization, CVSS 9.8) and SOB-2024-015 (Cross-Contract Reentrancy, CVSS 8.8).Installation and build
What Rust version does Sanctifier require?
What Rust version does Sanctifier require?
verify and prove commands additionally require the Z3 SMT solver C headers at build time. See the next question for details.The build fails with 'z3.h file not found'. How do I fix it?
The build fails with 'z3.h file not found'. How do I fix it?
verify and prove commands depend on the Z3 Rust bindings (z3-sys), which need the Z3 C header at compile time.macOS (Homebrew):analyze. Only verify and prove invoke the solver at runtime.The build fails with a 'libdbus-1' or 'dbus-sys' error on Linux.
The build fails with a 'libdbus-1' or 'dbus-sys' error on Linux.
libz3-dev.'sanctifier: command not found' after cargo install.
'sanctifier: command not found' after cargo install.
cargo install places binaries in ~/.cargo/bin. Ensure that directory is on your PATH:.bashrc, .zshrc, etc.) to make it permanent.Configuration
Why is my .sanctify.toml being ignored?
Why is my .sanctify.toml being ignored?
-
TOML syntax error. A malformed file is silently ignored and built-in defaults are used. The most frequent mistake is an unescaped backslash in a regex
pattern. Write"unsafe\\s*\\{"(double-escaped) or use a TOML literal string'unsafe\s*\{'. -
A closer file shadows yours. Sanctifier walks up from the scanned path and uses the first
.sanctify.tomlit finds. A config file nearer the target path silently wins. -
Wrong key expectation. Some keys are reserved for future use. For example,
enabled_rulescurrently records intent but does not gate individual detectors at runtime — the full detector set always runs. Use[[custom_rules]]to add or enforce specific patterns today.
cat .sanctify.toml | python3 -c "import sys, tomllib; tomllib.load(sys.stdin.buffer)" (Python 3.11+).How do I suppress a false positive finding?
How do I suppress a false positive finding?
-
Refactor to remove the ambiguity. Replace
unwrap()with explicit error handling, or+withchecked_add. This improves both the finding and the contract’s actual safety. -
Exclude the path. Add the file or directory to
ignore_pathsin.sanctify.tomlto skip generated code, fixtures, or vendored crates you do not own:
- Use text mode as advisory.
sanctifier analyzein the default text mode exits0regardless of findings. Only JSON mode (--format json) gates CI on critical/high issues, so you can review findings without blocking development until the signal is clean.
insta snapshots, so regressions are tracked.How do I add a project-specific detection rule?
How do I add a project-specific detection rule?
[[custom_rules]] table to .sanctify.toml with a name, a pattern (Rust-compatible regex), and an optional severity:S007. Use TOML literal strings ('...') for patterns containing backslashes to avoid double-escaping.Analysis and findings
How do I add Sanctifier to my CI pipeline?
How do I add Sanctifier to my CI pipeline?
--format json exits non-zero when there are critical or high findings, causing the CI job to fail. The default text mode is informational and always exits 0.For a full pipeline including formal verification:--strict causes verify to exit non-zero if any invariant is Refuted or Unknown.How do I generate a security badge for my README?
How do I generate a security badge for my README?
sanctifier badge:sanctifier-security.svg and paste the markdown from badge.md into your README.md. The badge displays Secure (green), Warning (orange), or Critical (red) based on whether the report contains critical or high findings.What does each S0xx finding code mean?
What does each S0xx finding code mean?
S001–S016 each correspond to a detector family:| Code | Detector |
|---|---|
| S001 | Authorization gap (missing require_auth) |
| S002 | Explicit panic! |
| S003 | Unchecked arithmetic (+, -, * on integers) |
| S004 | Ledger entry size approaching or exceeding limit |
| S005 | Storage key collision |
| S006 | unsafe block |
| S007 | Custom rule match |
| S008 | Event inconsistency |
| S009 | Unhandled Result |
| S010 | Upgrade / admin mechanism risk |
| S011 | Invariant refuted by SMT solver |
| S012 | Hardcoded address literal |
| S013 | Missing edge-amount validation |
| S014 | (reserved) |
| S015 | Dead code |
| S016 | Error code collision in #[contracterror] |
Why does analyze --format json fail my build but text mode does not?
Why does analyze --format json fail my build but text mode does not?
0. Adjust --limit or .sanctify.toml thresholds to tune what counts as blocking.Formal verification
What does PROVEN / REFUTED / UNKNOWN / KANI ↗ mean in verify output?
What does PROVEN / REFUTED / UNKNOWN / KANI ↗ mean in verify output?
sanctifier verify reports one of four statuses per invariant:| Status | Meaning |
|---|---|
| PROVEN | The Z3 SMT solver confirmed the invariant holds for all possible inputs within the model. |
| REFUTED | Z3 found a concrete counterexample that violates the invariant. The output includes the values that trigger the failure. |
| UNKNOWN | Z3 could not prove or refute the invariant within its resource limits (timeout or solver limits). Investigate manually or increase Z3 resources. |
| KANI ↗ | The invariant involves types (e.g. Env, Address) that the Z3 backend cannot model. Run cargo kani to verify it with Kani’s deeper function-level model checker. |
--strict to exit non-zero on REFUTED or UNKNOWN:Why does sanctifier prove require --invariant?
Why does sanctifier prove require --invariant?
sanctifier prove runs SMT proofs for one or more named token invariants against a specific contract path. The --invariant flag selects which invariant(s) to prove:all) can be expensive, and you often want to target a specific property during development. Without the flag the command cannot determine which SMT model to construct.Built-in invariant names:balance_non_negative— no account balance can go below zerosupply_conserved— total supply is unchanged by transfersno_unauthorized_mint— tokens cannot be minted without properrequire_authall— run all three sequentially
How do I use a custom vulnerability database?
How do I use a custom vulnerability database?
--vuln-db to sanctifier analyze with the path to your custom JSON file:id, name, description, severity, category, pattern, and recommendation. The pattern field is a Rust-compatible regex applied to .rs source files. See the CVE Database reference for the full JSON schema.My invariants are reported as 'Unsupported'. What is wrong?
My invariants are reported as 'Unsupported'. What is wrong?
Scoring and attestation
What does the Sanctity Score mean?
What does the Sanctity Score mean?
| Severity | Penalty per finding |
|---|---|
| Critical | −40 |
| High | −15 |
| Medium | −6 |
| Low | −2 |
sanctifier attest as part of a zero-knowledge attestation and is also embedded in the JSON report for use by the badge command. The score is bound to a SHA-256 commitment of the exact source bytes analyzed, so the attestation is tied to a specific version of the code.How do I generate a ZK attestation that my scan passed a score threshold?
How do I generate a ZK attestation that my scan passed a score threshold?
sanctifier attest:sanctifier attest --help for output path options.Error → fix quick reference
| Symptom / message | Likely cause | Fix |
|---|---|---|
fatal error: 'z3.h' file not found | Z3 dev headers not on include path | Install Z3; on macOS set Z3_SYS_Z3_HEADER env var |
Build fails on libdbus-1 / dbus-sys | D-Bus headers missing (Linux) | sudo apt-get install -y libdbus-1-dev |
sanctifier: command not found | ~/.cargo/bin not on PATH | export PATH="$HOME/.cargo/bin:$PATH" |
| Config edits have no effect | TOML parse error or shadowed by closer file | Fix TOML syntax; check for nearer .sanctify.toml |
| Custom rule never fires | Unescaped backslash in pattern | Use TOML literal string '...' or double-escape \\s |
analyze reports issues but CI still passes | Text mode is advisory (exits 0) | Gate with analyze --format json |
Invariants reported as Unsupported | No Z3 / built without SMT backend | Install Z3 and rebuild |
verify/prove exits non-zero in CI | Invariant is Refuted or Unknown (with --strict) | Fix the invariant or investigate the counterexample |
KANI ↗ status in verify output | Invariant uses host types Z3 cannot model | Run cargo kani for deeper model checking |
| OOG (out of gas) on invocation | Oversized state / unbounded loops | Reduce state, use Temporary storage, bound iterations |
| False positive auth gap | require_auth hidden behind indirection | Call require_auth directly in the entry point |
Glossary
Soroban
Soroban
wasm32-unknown-unknown), and executed deterministically by the Soroban host. Sanctifier is purpose-built for the Soroban execution model and its storage, authorization, and resource metering APIs.SEP-41
SEP-41
transfer, transfer_from, approve, mint, burn, balance, allowance, and metadata functions. The contracts/sep41-token-invariants contract is a reference implementation with Kani-verified proofs.require_auth
require_auth
Address::require_auth() (and require_auth_for_args) is the Soroban host call that asserts the given address authorized the current invocation. Any state-mutating entry point that omits it allows unauthorized callers to act — the most critical class of Soroban vulnerability, detected as finding code S001. Representative database entries include SOL-2024-001 (Unprotected Initialization, CVSS 9.8), SOL-2024-002 (Missing Auth on Token Transfer, CVSS 9.8), SOL-2024-006 (Unprotected Mint Function, CVSS 9.8), and SOB-2024-018 (Upgrade Authorization Bypass, CVSS 9.9).Kani
Kani
KANI ↗ when the Z3 backend cannot handle them, and the contracts/reentrancy-guard and contracts/amm-pool crates ship pre-written Kani harnesses. Requires a separate installation: see kani.model-checking.github.io.SMT / Z3
SMT / Z3
sanctifier verify and sanctifier prove. Given a set of constraints derived from your invariant annotations and the contract’s pure logic, Z3 either proves they are always satisfied (PROVEN) or finds a concrete counterexample (REFUTED). Requires the Z3 C library at build time (libz3-dev / brew install z3).WASM
WASM
wasm32-unknown-unknown target). Sanctifier performs source-level analysis of Rust files; it does not inspect compiled .wasm artifacts. Problems that only surface in the wasm32 target (e.g. a std-dependent transitive dependency) are build issues outside Sanctifier’s scope.Sanctity Score
Sanctity Score
sanctifier attest to generate a zero-knowledge proof of threshold compliance and by sanctifier badge to determine the badge color (green/orange/red).Baseline
Baseline
.sanctify-baseline.json by sanctifier baseline. On subsequent runs, sanctifier analyze compares new findings against the baseline and only reports net-new regressions — useful for gradually adopting Sanctifier in a codebase that already has known findings. Pass --no-baseline to ignore the baseline file and see the full finding list.Attestation
Attestation
sanctifier attest that binds a Sanctity Score to a SHA-256 commitment of the exact source bytes analyzed. An attestation can be shared publicly; any third party can verify the score claim without seeing the raw finding counts or source code. Useful for demonstrating security posture to auditors, partners, or token holders.guard_invariant
guard_invariant
sanctifier-guards crate used in runtime contract instrumentation. When called around a boolean invariant expression, it publishes a structured inv_fail event to the Soroban event log if the invariant breaks, enabling off-chain indexers to detect violations across all instrumented contracts by subscribing to the single inv_fail topic. The contracts/runtime-guard-wrapper contract demonstrates three concrete usage sites.