Runtime-aware SCA β proves which CVEs are actually reachable, not just installed.
VulnReach is now an official OWASP Project. π
Language support: Python is fully production-ready (taint, AST, route, runtime). Java and JavaScript have functional call graph analysis and are experimental. Go, C#, and PHP are on the roadmap. See ROADMAP.md for details.
VulnReach builds on standard SCA output by adding reachability context β proving through static analysis, taint tracking, and live runtime coverage which of the detected CVEs can actually be reached in your application.
- Dependency-aware parallel runner pipeline for faster scans
- Python reachability β production-ready (taint, AST, route, runtime layers all functional)
- Java reachability β functional call graph with Maven/Gradle dependency parsing (experimental)
- JavaScript reachability β functional call graph with route entry point detection (experimental)
- Scan cancellation β
POST /scan/{id}/cancelstops in-progress scans - Stable scan response contract:
summary+ classified buckets onGET /scan/{id} - Shared scan response normalization across API and package local mode (parity)
- Secure-by-default runtime boundary:
- base compose runs without Docker socket mount
- dynamic scans require explicit opt-in via
VULNREACH_ALLOW_DOCKER_DAEMON=true - runtime profile uses restricted
docker-socket-proxy
- Deterministic fixture quality gates for Java/JavaScript/Go in CI
- Accepted as an official OWASP Project β owasp.community/projects/vulnreach
- AI next-steps endpoint β
POST /findings/{id}/next-stepsproduces analyst-facing remediation guidance (immediate actions, validation probes, upgrade paths, monitoring) for a deterministic finding. Lazy / on-demand: scans never call the LLM, and LLM failures degrade gracefully. The deterministic verdict is read-only. See docs/api.md.
scan.runtime.ebpftracing mode (Linux-focused, explicit opt-in)- AI-assisted OpenAPI generation and Intelligent DAST flows
See:
Each CVE is classified through a five-layer evidence chain:
1. SCA (Trivy) β is the package installed and vulnerable?
2. Taint analysis (tainter) β does user input flow to the vulnerable sink?
3. AST analysis β is the vulnerable function in your call graph?
4. Route exposure β is the call path reachable from an HTTP endpoint?
5. Runtime coverage β was the vulnerable code actually executed?
The result is a prioritised finding list with four tiers:
| Tier | Meaning |
|---|---|
DYNAMICALLY_REACHABLE |
Runtime coverage confirmed execution β fix immediately |
STATICALLY_REACHABLE |
Code path proven via AST/taint β high priority |
UNCERTAIN |
Weak signal only β investigate |
NOT_REACHABLE |
No evidence β suppress from alert queue |
Security notice β before starting, copy
.env.exampleto.env.localand replace everyCHANGE_MEvalue with a strong random secret.
Do not expose VulnReach on a public network without setting real credentials and configuringCORS_ORIGINS.
git clone https://github.com/ihrishikesh0896/vulnreach.git
cd vulnreach
# 1. Create your local config
cp .env.example .env.local
# 2. Fill in every CHANGE_ME β generate secrets with: openssl rand -hex 32
$EDITOR .env.local
# 3. Start the stack
docker compose up --build
# Optional: enable dynamic runtime scans (Docker daemon access via restricted socket proxy)
# docker compose -f docker-compose.yml -f docker-compose.runtime.yml up --buildAuth options:
- Short-lived JWT:
POST /login - Long-lived API token (API key): create in UI
Settings -> API Keys, then use it asAuthorization: Bearer <API_KEY>
# Get a token (replace with the credentials you set in .env.local)
TOKEN=$(curl -s -X POST http://localhost:8000/login \
-H "Content-Type: application/json" \
-d '{"username":"<your-admin-user>","password":"<your-admin-password>"}' | jq -r .access_token)
# Start scan from a GitHub repo
curl -X POST http://localhost:8000/scan \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"repo_url":"https://github.com/yourorg/yourapp"}'
# Poll for results
curl http://localhost:8000/scan/<scan_id> \
-H "Authorization: Bearer $TOKEN" | jq .summary- Reachability-filtered SCA β classifies each CVE by evidence strength, not just CVSS score
- Runtime confirmation β Docker-based coverage collection via
coverage.py - Taint tracking β traces user input β vulnerable sinks (SQL, subprocess, YAML, pickle)
- LLM-steered DAST β Claude/OpenAI/Ollama generates and validates exploit payloads (optional)
- CI/CD gates β
policy.block_iffails builds on confirmed critical findings - JWT auth β multi-user, role-based access (admin / analyst)
- API tokens (API keys) β long-lived machine auth for curl/CI (
Authorization: Bearer <API_KEY>) - PDF export β
GET /scan/{id}/export/pdf - No vendor lock-in β LLM features default to
provider: none; Ollama supported for offline use
Scan target: multi-tier-dvpa β an intentionally vulnerable Python/Django application with 72 raw CVEs across 11 packages.
| Layer | Result |
|---|---|
| Raw CVEs (Trivy) | 72 |
| Classified findings (VulnReach) | 90 |
| DYNAMICALLY_REACHABLE β fix now | 49 |
| STATICALLY_REACHABLE β fix this sprint | 23 |
| UNCERTAIN β investigate | 18 |
| NOT_REACHABLE β suppress | 0 |
| CI pipeline gate | BLOCKED |
46% of findings were moved out of the undifferentiated "fix everything" queue into a prioritised action list. In a typical production service (where many transitive dependencies are never called), this figure rises to 70β90%.
Full methodology, evidence chain detail, and package-level breakdown: docs/benchmark.md
- USAGE_PACKAGE.md β package/CLI installation, dependencies, startup, usage
- USAGE_UI.md β UI/server installation, dependencies, startup, usage
- docs/deployment.md β Docker Compose setup, env vars, production notes
- docs/configuration.md β full
scan.ymlconfig reference - docs/api.md β REST endpoints and schemas
- docs/architecture.md β pipeline design and execution model
- docs/threat-model.md β trust boundaries, STRIDE, abuse cases
- docs/incubator-readiness.md β OSS/OWASP readiness status
- docs/DAST.md β DAST concepts and flow
- ROADMAP.md β planned features, known limitations, language support status
- docs/development.md β internals, agents, storage, extension points
- OWASP.md β OWASP project notes
- SECURITY.md β vulnerability disclosure and key rotation
- CONTRIBUTING.md β contribution process
- CHANGELOG.md β release history
- Python 3.11+
- PostgreSQL 13+
- Docker + Docker Compose v2 (for dynamic analysis)
trivyon PATH (install)jq(used in quick start examples β install)
Optional (all skip gracefully if absent):
semgrepβpip install semgreptainterβpip install tainter(taint-flow analysis; see development guide)
Apache 2.0 β see LICENSE.




