Skip to content

Repository files navigation

RytScan

A fast, zero-config security scanner for Soroban smart contracts on Stellar.

CIRustLicenseRulesSARIFCode Scanning

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).


Why RytScan?

Wave needRytScan coverage
Soroban contract security before merge9 built-in rules (AUTH, PANIC, TOKEN, EVENT, TTL, STORE, ARITH, ASSERT, UNSAFE)
Event emission for indexersEVENT-001 flags state changes without env.events().publish
CI gate for contract PRs--fail-on high exit code + SARIF for GitHub Code Scanning
Contributor onboardingFixture contracts + rytscan rules catalog

Complements ecosystem tools like OpenZeppelin's Soroban security detectors and Sanctifier with a Wave-focused, fast, zero-config entry point.


Install

From source (recommended)

git clone https://github.com/BreachDirect/RytScan.git
cd RytScan
cargo install --path crates/rytscan-cli --locked
rytscan --version

Build the binary directly

cargo build --release
./target/release/rytscan --version

MSRV: Rust 1.95+ (see rust-version in the workspace Cargo.toml).


Quick Start

# 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

Example output

$ 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.
...

Exit codes

CodeMeaning
0Scan complete, no findings at/above the --fail-on threshold
1Findings found at or above the threshold
2Invalid scan path or runtime error

Scan options

FlagDefaultDescription
scan <path>Contract file or directory to analyze
--format <text|json|sarif>textOutput format; sarif is SARIF v2.1.0
--rule <ID>all rulesRestrict to specific rule IDs (repeatable, e.g. --rule AUTH-001)
--include-testsoffAlso scan Rust files under tests//test dirs
--fail-on <severity>highExit 1 when a finding is at/above this severity (info|low|medium|high|critical)
--versionPrint the RytScan version
rulesList built-in rule IDs and titles

Unknown rule IDs are rejected with a pointer to rytscan rules.


Built-in Rules

Rule IDSeverityDetects
AUTH-001HighState-changing functions without require_auth()
PANIC-001Mediumunwrap(), expect(), panic!() in contract code
TOKEN-001HighUnchecked SEP-41 transfer() return values
EVENT-001LowState changes without Soroban event emission
TTL-001MediumPersistent storage writes without extend_ttl()
STORE-001HighDurable state stored in temporary storage
ARITH-001Highunchecked_* arithmetic that can overflow
ASSERT-001Mediumassert! macros that abort the transaction
UNSAFE-001Highunsafe blocks in on-chain code

Each rule documents its CWE class, detection strategy, and a fix example in docs/rules.md.


CI integration

As a merge gate

# .github/workflows/rytscan.ymlname: RytScanon:
pull_request:
jobs:
scan:
runs-on: ubuntu-lateststeps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Install RytScanrun: cargo install --path crates/rytscan-cli --locked
- name: Scan contractsrun: rytscan scan contracts/ --fail-on high

As a GitHub Code Scanning step

RytScan 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 SARIFrun: rytscan scan contracts/ --format sarif --fail-on critical > rytscan.sarif
- name: Upload to Code Scanninguses: github/codeql-action/upload-sarif@v3with:
sarif_file: rytscan.sarifcategory: rytscan

Set --fail-on to your preferred blocking severity. For Code Scanning uploads we recommend critical so the scan step still exits 0 for actionable high findings that the SARIF upload reports in the Security tab.


How it works

┌────────────┐ ┌───────────────────────────┐ ┌───────────────┐
│ 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.


Project Structure

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)

Limitations

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.


Roadmap

PhaseFocusStatus
1CLI, core rules, fixtures, PRD/architecture✅ Complete
1.5ARITH/ASSERT/UNSAFE rules, SARIF, CI workflow✅ Complete
2syn AST parser, suppressions, GitHub ActionPlanned
3WASM bytecode checks, testnet invoke probesPlanned
4Web dashboard + Wave issue triage integratorPlanned

See docs/ROADMAP.md, docs/prd.md, and the issue tracker.


Development

cargo fmt --all -- --check
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace
cargo audit # dependency vulnerability scan

See CONTRIBUTING.md for the full contributor guide, CODE_OF_CONDUCT.md for community standards, and SECURITY.md for reporting vulnerabilities.


License

MIT — see LICENSE. Copyright (c) 2026 BreachDirect.

About

Fast, zero-config static security scanner for Soroban smart contracts on Stellar. 9 built-in rules, text/JSON/SARIF output, and a CI merge gate for GitHub Code Scanning.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages