Skip to content

Latest commit

 

History

77 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

VulnReach

Runtime-aware SCA — proves which CVEs are actually reachable, not just installed.

OWASP Project License Python

VulnReach is now an official OWASP Project. 🎉

Demo

VulnReach Demo

Step 1 — SCA surfaces 74 CVEs across dependencies

Trivy SCA output — 74 vulnerabilities detected

Step 2 — VulnReach proves which ones are actually reachable

Fix Plan — 7 packages, 50 confirmed reachable CVEs with upgrade targets


Findings — evidence chain per CVE

Dynamically reachable findings with full evidence chain

Dashboard — 42 confirmed reachable across 9 repos

VulnReach Dashboard

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.


Project Status

Latest Development (shipped)

  • 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 cancellationPOST /scan/{id}/cancel stops in-progress scans
  • Stable scan response contract: summary + classified buckets on GET /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 Projectowasp.community/projects/vulnreach
  • AI next-steps endpointPOST /findings/{id}/next-steps produces 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.

Experimental

  • scan.runtime.ebpf tracing mode (Linux-focused, explicit opt-in)
  • AI-assisted OpenAPI generation and Intelligent DAST flows

See:


How it works

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

Quick Start

With Docker Compose (recommended)

Security notice — before starting, copy .env.example to .env.local and replace every CHANGE_ME value with a strong random secret.
Do not expose VulnReach on a public network without setting real credentials and configuring CORS_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 --build

Run a scan

Auth options:

  • Short-lived JWT: POST /login
  • Long-lived API token (API key): create in UI Settings -> API Keys, then use it as Authorization: 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

Features

  • 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 gatespolicy.block_if fails 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 exportGET /scan/{id}/export/pdf
  • No vendor lock-in — LLM features default to provider: none; Ollama supported for offline use

In Practice

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


Documentation

Usage

  • USAGE_PACKAGE.md — package/CLI installation, dependencies, startup, usage
  • USAGE_UI.md — UI/server installation, dependencies, startup, usage

Operators / Deployers

Architecture / Security

Contributors


Requirements

  • Python 3.11+
  • PostgreSQL 13+
  • Docker + Docker Compose v2 (for dynamic analysis)
  • trivy on PATH (install)
  • jq (used in quick start examples — install)

Optional (all skip gracefully if absent):

  • semgreppip install semgrep
  • tainterpip install tainter (taint-flow analysis; see development guide)

License

Apache 2.0 — see LICENSE.

About

Runtime-aware SCA — proves which CVEs are actually reachable, not just installed.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

13 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages