A fast, zero-config security scanner for Soroban smart contracts on Stellar.
RytScan is a lightweight static analysis CLI that catches common security issues in Soroban contracts before they reach testnet — missing authorization, panic-prone error handling, unchecked token transfers, missing events, unsafe arithmetic, and unsafe storage patterns. It runs locally, never sends your source code anywhere, and drops straight into CI as a merge gate or a GitHub Code Scanning step.
Built for the Stellar Wave 8 program (August 2026).
| Wave need | RytScan coverage |
|---|---|
| Soroban contract security before merge | 9 built-in rules (AUTH, PANIC, TOKEN, EVENT, TTL, STORE, ARITH, ASSERT, UNSAFE) |
| Event emission for indexers | EVENT-001 flags state changes without env.events().publish |
| CI gate for contract PRs | --fail-on high exit code + SARIF for GitHub Code Scanning |
| Contributor onboarding | Fixture contracts + rytscan rules catalog |
Complements ecosystem tools like OpenZeppelin's Soroban security detectors and Sanctifier with a Wave-focused, fast, zero-config entry point.
git clone https://github.com/BreachDirect/RytScan.git
cd RytScan
cargo install --path crates/rytscan-cli --locked
rytscan --versioncargo build --release
./target/release/rytscan --versionMSRV: Rust 1.95+ (see
rust-versionin the workspaceCargo.toml).
# Scan a contract directory (text output, fail on high-severity findings)
rytscan scan ./my-contract
# JSON output for CI pipelines
rytscan scan ./my-contract --format json --fail-on high
# SARIF v2.1.0 output for GitHub Code Scanning
rytscan scan ./my-contract --format sarif > rytscan.sarif
# Scan a single file
rytscan scan path/to/contract/src/lib.rs
# Only run specific rules (repeatable)
rytscan scan ./my-contract --rule AUTH-001 --rule ARITH-001
# List all built-in rules
rytscan rules$ rytscan scan fixtures/vulnerable-vault/src
RytScan v0.1.0
Target: fixtures/vulnerable-vault/src
Scanned 1 file(s) with 9 rule(s) — 19 finding(s)
[HIGH] lib.rs:60 — Missing require_auth on privileged function (AUTH-001)
Function `withdraw` modifies state but never calls require_auth()
> pub fn withdraw(env: Env, user: Address, amount: i128) {
fix: Call env.storage().instance().get(&DataKey::Admin) or the relevant
signer address, then invoke require_auth() before mutating vault state.
[HIGH] lib.rs:60 — Unchecked SEP-41 token transfer (TOKEN-001)
Token transfer return value is not checked
> token.transfer(&user, amount);
fix: Check the bool returned by token.transfer() or use a helper that maps
failure to ContractError.
...
| Code | Meaning |
|---|---|
0 |
Scan complete, no findings at/above the --fail-on threshold |
1 |
Findings found at or above the threshold |
2 |
Invalid scan path or runtime error |
| Flag | Default | Description |
|---|---|---|
scan <path> |
— | Contract file or directory to analyze |
--format <text|json|sarif> |
text |
Output format; sarif is SARIF v2.1.0 |
--rule <ID> |
all rules | Restrict to specific rule IDs (repeatable, e.g. --rule AUTH-001) |
--include-tests |
off | Also scan Rust files under tests//test dirs |
--fail-on <severity> |
high |
Exit 1 when a finding is at/above this severity (info|low|medium|high|critical) |
--version |
— | Print the RytScan version |
rules |
— | List built-in rule IDs and titles |
Unknown rule IDs are rejected with a pointer to rytscan rules.
| Rule ID | Severity | Detects |
|---|---|---|
AUTH-001 |
High | State-changing functions without require_auth() |
PANIC-001 |
Medium | unwrap(), expect(), panic!() in contract code |
TOKEN-001 |
High | Unchecked SEP-41 transfer() return values |
EVENT-001 |
Low | State changes without Soroban event emission |
TTL-001 |
Medium | Persistent storage writes without extend_ttl() |
STORE-001 |
High | Durable state stored in temporary storage |
ARITH-001 |
High | unchecked_* arithmetic that can overflow |
ASSERT-001 |
Medium | assert! macros that abort the transaction |
UNSAFE-001 |
High | unsafe blocks in on-chain code |
Each rule documents its CWE class, detection strategy, and a fix example in
docs/rules.md.
# .github/workflows/rytscan.yml
name: RytScan
on:
pull_request:
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Install RytScan
run: cargo install --path crates/rytscan-cli --locked
- name: Scan contracts
run: rytscan scan contracts/ --fail-on highRytScan emits SARIF 2.1.0 compatible
with GitHub's codeql-action/upload-sarif, so findings appear in the Security
tab of your repo:
- name: Generate SARIF
run: rytscan scan contracts/ --format sarif --fail-on critical > rytscan.sarif
- name: Upload to Code Scanning
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: rytscan.sarif
category: rytscanSet
--fail-onto your preferred blocking severity. For Code Scanning uploads we recommendcriticalso the scan step still exits0for actionablehighfindings that the SARIF upload reports in the Security tab.
┌────────────┐ ┌───────────────────────────┐ ┌───────────────┐
│ rytscan-cli │──▶│ rytscan-core (rule engine)│──▶│ Report model │
│ (clap CLI) │ │ 9 detectors · file walker │ │ text / JSON / │
└────────────┘ └─────────────┬─────────────┘ │ SARIF 2.1.0 │
│ walk *.rs files └───────┬───────┘
▼ ▼
RuleContext GitHub Code Scanning
(file, source, lines)
Each rule is a small, independently testable detector implementing the Rule
trait. Phase 1 uses function-block extraction (brace counting) plus line
heuristics; Phase 2 replaces this with a syn AST visitor for fewer false
positives. See docs/architecture.md for details.
RytScan/
├── crates/
│ ├── rytscan-core/ # Rule engine + scanner + SARIF serializer
│ └── rytscan-cli/ # rytscan binary
├── fixtures/ # Vulnerable + clean sample contracts
├── docs/
│ ├── prd.md
│ ├── architecture.md
│ ├── rules.md
│ └── ROADMAP.md
└── .github/workflows/ # CI (fmt, clippy, audit, tests, smoke)
RytScan is a static analyzer. It cannot detect runtime-only bugs, economic exploits, or logic errors that require execution. Phase 1 heuristics may produce false positives on complex macros; suppression support arrives in Phase 2. For on-chain verification, see the Phase 3 roadmap.
| Phase | Focus | Status |
|---|---|---|
| 1 | CLI, core rules, fixtures, PRD/architecture | ✅ Complete |
| 1.5 | ARITH/ASSERT/UNSAFE rules, SARIF, CI workflow | ✅ Complete |
| 2 | syn AST parser, suppressions, GitHub Action |
Planned |
| 3 | WASM bytecode checks, testnet invoke probes | Planned |
| 4 | Web dashboard + Wave issue triage integrator | Planned |
See docs/ROADMAP.md, docs/prd.md, and the
issue tracker.
cargo fmt --all -- --check
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace
cargo audit # dependency vulnerability scanSee CONTRIBUTING.md for the full contributor guide, CODE_OF_CONDUCT.md for community standards, and SECURITY.md for reporting vulnerabilities.
MIT — see LICENSE. Copyright (c) 2026 BreachDirect.