npx skills add ...
npx skills add trailofbits/skills --skill cairo-vulnerability-scanner
Scans Cairo/StarkNet smart contracts for 6 critical vulnerabilities including felt252 arithmetic overflow, L1-L2 messaging issues, address conversion problems, and signature replay. Use when auditing StarkNet projects.
npx skills add trailofbits/skills --skill cairo-vulnerability-scanner
Systematically scan Cairo smart contracts on StarkNet for platform-specific security vulnerabilities related to arithmetic, cross-layer messaging, and cryptographic operations. This skill encodes 6 critical vulnerability patterns unique to Cairo/StarkNet ecosystem.
.cairosrc/contract.cairo - Main contract implementationsrc/lib.cairo - Library modulestests/ - Contract testsScarb.toml - Cairo project configurationcargo install --git https://github.com/crytic/caracal --profile release --force (a Rust tool — not on PyPI)caracal detect src/When invoked, I will:
When vulnerabilities are found, you'll get a report like this:
I check for 6 critical vulnerability patterns unique to Cairo/Starknet. For detailed detection patterns, code examples, mitigations, and testing strategies, see VULNERABILITY_PATTERNS.md.
felt252 wraps silently; use u128/u256For complete vulnerability patterns with code examples, see VULNERABILITY_PATTERNS.md.
src/*.cairo)For each #[l1_handler] function:
from_address parameterFor signature-based functions:
If contract includes bridge functionality:
Report on every pattern in §6, whether or not it turned anything up. Emit this table above the findings, with all 6 rows present:
| # | Pattern | Verdict | Evidence |
|---|---|---|---|
| 1 | Felt252 Arithmetic Overflow/Underflow | clear | balances are u256; searched felt252 in arithmetic, none |
| 2 | L1 to L2 Address Conversion | ||
| 3 | L1 to L2 Message Failure | ||
| 4 | Overconstrained L1 <-> L2 Interaction | ||
| 5 | Signature Replay Protection | ||
| 6 | Unchecked from_address in L1 Handler |
Each verdict is one of:
found — cite file:line and write the finding up in full below.clear — the pattern applies to this contract and the contract handles it. Name the function, trait, or
check you searched for, so a reader can repeat the search.n/a — the pattern cannot apply here. Give the reason in one clause ("no L1 handlers in this contract").
Not having looked is not n/a.A table with fewer than 6 rows is an incomplete scan and must be reported as one. A row whose Verdict cell is empty is incomplete in the same way: row 1 above is filled in to show the shape, and every row is filled in the same way before the report is done. Six clear verdicts is a
result a reader can act on. A report that covers two patterns and says nothing about the other four reads
exactly like a clean contract, and that is the failure this table exists to prevent.
building-secure-contracts/not-so-smart-contracts/cairo/Before completing Cairo/StarkNet audit:
Arithmetic Safety (HIGH):
L1 Handler Security (CRITICAL):
#[l1_handler] functions validate from_addressL1-L2 Messaging (HIGH):
Signature Security (HIGH):
Tool Usage:
found, clear or n/a with a reasonn/a costs one
clause and makes the judgment reviewable. Silence records nothing, and a reader cannot tell it apart from
not having checked.felt252 does not behave
like the sized integer types, and the boundary between them is where pattern 4 lives.from_address is the canonical StarkNet bridge bug.=== CAIRO/STARKNET VULNERABILITY SCAN RESULTS ===# Find felt252 usage in arithmetic
rg "felt252" src/ | rg "[-+*/]"
# Find balance/amount storage using felt252
rg "felt252" src/ | rg "balance|amount|total|supply"
# Should prefer u128, u256 instead# Run Caracal detectors
caracal detect src/
# Specific detectors
caracal detect src/ --detectors unchecked-felt252-arithmetic
caracal detect src/ --detectors unchecked-l1-handler-from
caracal detect src/ --detectors missing-nonce-validation#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_felt252_overflow() {
// Test arithmetic edge cases
}
#[test]
#[should_panic]
fn test_unauthorized_l1_handler() {
// Wrong from_address should fail
}
#[test]
fn test_signature_replay_protection() {
// Same signature twice should fail
}
}// Test full L1-L2 flow
#[test]
fn test_deposit_withdraw_roundtrip() {
// 1. Deposit on L1
// 2. Wait for L2 processing
// 3. Verify L2 balance
// 4. Withdraw to L1
// 5. Verify L1 balance restored
}# .github/workflows/security.yml
- name: Run Caracal
run: |
# Rebuilds from source each run; cache ~/.cargo or pin a release binary instead.
cargo install --git https://github.com/crytic/caracal --profile release --force
caracal detect src/ --fail-on high,critical