Version: 1.1
Last updated: 2026-08-05
RytScan is a Rust workspace with a library crate (rule engine) and a CLI binary.
graph LR
CLI[rytscan-cli] --> CORE[rytscan-core]
CORE --> RULES[Rule Engine]
CORE --> SCAN[Directory Scanner]
RULES --> OUT[Report Text/JSON]
CORE --> SARIF[SARIF 2.1.0 Serializer]
SARIF --> GCS[GitHub Code Scanning]
SCAN --> FS[(.rs Soroban sources)]
| Crate | Role |
|---|---|
rytscan-core |
Rule trait, 9 detectors, report model, file walker, SARIF serializer |
rytscan-cli |
Clap CLI, output formatting, exit codes |
sequenceDiagram
participant User
participant CLI as rytscan-cli
participant Scanner
participant Rules
participant Report
User->>CLI: rytscan scan ./contracts
CLI->>Scanner: scan_path(target)
Scanner->>Scanner: collect *.rs files
loop each file
Scanner->>Rules: run(ctx)
Rules-->>Scanner: Vec<Finding>
end
Scanner->>Report: aggregate + sort
Report-->>CLI: Report
CLI-->>User: text or JSON
- Recursively walks target directory via
walkdir - Includes
*.rsfiles; excludes/tests/and*_test.rsby default --include-testsoverrides exclusion
Each rule receives:
RuleContext {
file: &str, // relative path
source: &str, // full file contents
lines: &[String] // line-indexed for snippets
}Phase 1 uses function-block extraction (brace counting) and line heuristics. Phase 2 replaces this with syn AST visitors.
| ID | Engine | Severity | Detection strategy |
|---|---|---|---|
| AUTH-001 | Function analysis | High | State-changing pub fn without require_auth |
| PANIC-001 | Line scan | Medium | unwrap, expect, panic! |
| TOKEN-001 | Line scan | High | .transfer( without result check |
| EVENT-001 | Function analysis | Low | State change without env.events() |
| TTL-001 | Function analysis | Medium | .persistent().set without extend_ttl |
| STORE-001 | Line scan | High | .temporary().set with durable keys |
| ARITH-001 | Line scan | High | unchecked_add/unchecked_sub/unchecked_mul (overflow risk) |
| ASSERT-001 | Line scan | Medium | assert!/assert_eq! macros (abort on failure) |
| UNSAFE-001 | Line scan | High | unsafe { } blocks (memory safety) |
Full rule descriptions: docs/rules.md.
{
"tool": "RytScan",
"version": "0.1.0",
"target": "fixtures/vulnerable-vault/src",
"summary": {
"files_scanned": 1,
"rules_run": 9,
"findings": 19,
"by_severity": { "high": 10, "medium": 3, "low": 6 }
},
"findings": [ ... ]
}--format sarif produces a SARIF 2.1.0 log with one rule entry per detector
(helpUri → docs/rules.md) and per-finding level mapped
from severity (high → error, medium → warning, low → note).
Exit codes:
| Code | Meaning |
|---|---|
| 0 | Scan complete, no findings ≥ --fail-on threshold |
| 1 | Findings at or above threshold |
| 2 | Invalid path / runtime error |
fixtures/
├── vulnerable-vault/src/lib.rs # intentional issues for regression
└── clean-token/src/lib.rs # passes high-severity checks
Used by cargo test in rytscan-core and documented in README quick start.
graph TB
CLI --> CORE
CORE --> SYN[syn AST Visitor]
GHA[GitHub Action] --> CLI
CORE --> CONFIG[rytscan.toml suppressions]
- Static only: Cannot detect runtime-only bugs or economic exploits
- Heuristic: Phase 1 may false-positive on complex macros; suppressions come in Phase 2
- No network: Scanner never sends source code off-machine
- Fail closed in CI: Default
--fail-on highblocks merges on auth/token issues
| Phase | Drips contributor workflow |
|---|---|
| 1/1.5 ✅ | rytscan scan . + --format sarif before opening Wave PR |
| 2 | GitHub Action comment on PR with findings |
| 3 | Testnet deploy checklist includes RytScan + invoke probe |
| 4 | Match scan gaps to open Wave security issues |
Browse: Drips Stellar Wave Issues