Static analysis + LLM triage for Solidity repos. 101 Slither detectors, 5 custom analyzers, 3 output formats.
- Python 3.11+
- Foundry (for Foundry repos)
- Git
pip install -e ".[dev]"# Quick scan (no LLM, raw findings)
python3.11 -m src.cli https://github.com/user/repo
# Full scan (with LLM triage + remediation)
python3.11 -m src.cli https://github.com/user/repo --depth full
# Output formats
python3.11 -m src.cli https://github.com/user/repo --output markdown sarif json
# Dry run (analyzers only, zero LLM calls)
python3.11 -m src.cli https://github.com/user/repo --dry-run{
"mcpServers": {
"scr-reviewer": {
"command": "python3.11",
"args": ["-m", "src.server"],
"env": {
"OPENAI_API_KEY": "sk-...",
"SCR_LLM_PROVIDER": "openai"
}
}
}
}- Clone — shallow clone with auto branch detection + submodule init
- Detect — multi-framework: Foundry, Hardhat, Truffle, bare
.sol - Discover — enum contracts, classify roles (core/test/mock/interface)
- Compile — per sub-project compilation
- Analyze — 5 analyzers, 101 Slither detectors:
Analyzer Detectors What it finds Slither 101 Reentrancy, delegatecall, overflow, access, timestamps, etc. Upgradeable 7 UUPS/Transparent/Beacon proxies, storage gaps, initializer guards Storage Layout 4 Storage collisions, unbounded arrays, mapping growth Access Control 5 Privileged functions, role mapping, sensitive ops behind admin gates Dependencies 3 Known-vulnerable OZ/solmate versions, unverified remappings - LLM Triage (optional) — severity adjustment, false-positive scoring, concrete remediation, consensus check on Critical/High
- Report — Markdown, SARIF (GitHub code scanning), JSON
Key env vars:
| Variable | Default | Description |
|---|---|---|
SCR_LLM_PROVIDER |
openai |
openai, anthropic, local |
SCR_LLM_MODEL |
gpt-4o |
Model name |
OPENAI_API_KEY |
— | OpenAI key |
ANTHROPIC_API_KEY |
— | Anthropic key |
SCR_NO_SANDBOX |
— | Skip Docker (unsafe) |
SCR_KEEP_WORKSPACE |
— | Don't clean up cloned repo |
SCR_CACHE_TTL_HOURS |
24 |
Cache TTL |
Full list in src/config.py.
Implement src.pipeline.analyzer.Analyzer and register in src/pipeline/analyzers/__init__.py:
class MyAnalyzer(Analyzer):
name = "my_analyzer"
version = "0.1.0"
async def analyze(self, repo_path, sub_project, contracts):
return [Finding(...)]See docs/limitations.md.