Kani
Kani
Kani is a bounded model checker for Rust, built by AWS. It automatically verifies that your Rust code is free of panics, overflows, out-of-bounds access, and assertion violations — across all possible inputs up to a configurable bound.
What Kani Does
You write a proof harness (like a test, but exhaustive) and Kani checks every possible input:
use neutron::handler::{Request, Response};
fn calculate_discount(price: u64, percent: u8) -> u64 {
price - (price * percent as u64 / 100)
}
#[kani::proof]
fn verify_discount_never_overflows() {
let price: u64 = kani::any();
let percent: u8 = kani::any();
kani::assume(percent <= 100);
kani::assume(price <= 1_000_000_00); // max $1M in cents
let result = calculate_discount(price, percent);
assert!(result <= price); // discount can't exceed original price
}
What It Catches
- Arithmetic overflow/underflow — integer wrapping, division by zero
- Out-of-bounds access — array/slice indexing beyond length
- Unwrap on None/Err — panics from
.unwrap()on bad values - Assertion violations — any
assert!ordebug_assert!that can fail - Undefined behavior in unsafe blocks — null pointers, dangling references
How to Use
1. Install Kani
cargo install --locked kani-verifier
cargo kani setup
2. Write Proof Harnesses
Add #[kani::proof] to functions in your test modules:
#[cfg(kani)]
mod verification {
use super::*;
#[kani::proof]
fn verify_auth_check() {
let role: u8 = kani::any();
let resource: u8 = kani::any();
// Kani tries ALL role/resource combinations
let allowed = check_permission(role, resource);
// Admin (role 0) should always have access
if role == 0 {
assert!(allowed);
}
}
}
3. Run
cargo kani
Kani reports either VERIFIED (proven correct) or shows a concrete counterexample that triggers the bug.
Bounded vs Unbounded
Kani is bounded — it checks all inputs up to a configurable limit. For most application code (handlers, business logic, data transforms), the default bounds are sufficient. For mathematical proofs over infinite domains, see Lean 4.
For full unbounded correctness proofs on Rust code, Verus will provide that capability when it becomes available as a standard cargo dependency.
When to Use Kani
- Validating business logic (pricing, permissions, state machines)
- Checking handler functions can't panic on any input
- Verifying
unsafeblocks in performance-critical code - Proving invariants in data structures (balanced trees, sorted arrays)
- Pre-deploy confidence on critical code paths