Echo-V is an autonomous DevSecOps system that detects CVEs, plans a fix, generates a patch, validates it in an isolated environment, and opens a pull request without any human involvement in the remediation loop.
Scout → Triage → Architect → Patch → [Sandbox ‖ Guardrail] → PR
When a CVE is reported against a repository, Echo-V:
- Fetches CVE details from NVD and OSV in parallel
- Scores the vulnerability using CVSSv3 and EPSS to assign a P0/P1/P2 priority
- Uses Claude to reason through a patch strategy before writing any code
- Generates a minimal code patch via Claude's structured
tool_useAPI - Runs the patch in an isolated E2B micro-VM (or Docker fallback) with no network access
- Walks the generated code with a Python AST checker that blocks dangerous patterns
- Opens a pull request using a short-lived GitHub App installation token
The dashboard streams live pipeline state to the browser over SSE, rendering an animated graph of the agent pipeline with per-stage status and event logs.
echo-V/
├── apps/
│ ├── dashboard/ Next.js 15, React 19, Framer Motion, React Flow
│ └── agent-brain/ FastAPI, LangGraph, Anthropic Claude, pgvector
├── packages/
│ ├── security/ Shared Zod schemas — the validation boundary
│ └── ui/ Shared component primitives
└── tooling/typescript/ Shared tsconfig base
| # | Stage | What it does |
|---|---|---|
| 1 | Scout | Fetches CVE data from NVD + OSV |
| 2 | Triage | CVSSv3 + EPSS → P0/P1/P2 priority |
| 3 | Architect | Claude plans the patch strategy |
| 4 | Patch | Claude generates the code change |
| 5 | Sandbox | Runs the patch in an isolated VM |
| 5 | Guardrail | AST-walks the generated code for dangerous patterns |
| 6 | PR | Opens a GitHub pull request |
Sandbox and Guardrail run in parallel. The PR node only proceeds when both pass.
AST guardrail — Every LLM-generated patch is walked by a Python AST visitor before any execution. Blocked patterns include eval, exec, subprocess.*, os.system, shutil.rmtree, shell injection strings, and hardcoded credentials.
No long-lived tokens — GitHub authentication uses short-lived App installation tokens (1h TTL) generated via JWT signing. No Personal Access Tokens.
OIDC + PKCE — Dashboard login via NextAuth v5 with GitHub as the OIDC provider.
SSE validation — Every agent event is re-validated against a Zod schema at the Next.js edge proxy before reaching the browser.
Audit log — Every agent decision is written to an append-only Postgres table per NIST AI RMF logging standards.
Sandbox isolation — Patches execute in an E2B micro-VM or Docker container with network disabled, a read-only root filesystem, and CPU/memory caps.
| Layer | Technology |
|---|---|
| Frontend | Next.js 15, React 19, Framer Motion, React Flow |
| Auth | NextAuth v5, OIDC + PKCE, GitHub App |
| Agent orchestration | LangGraph (StateGraph), FastAPI, Python 3.12 |
| LLM | Anthropic Claude (claude-opus-4-6) with prompt caching |
| Real-time | Server-Sent Events, Redis pub/sub |
| Database | PostgreSQL 16 + pgvector |
| Cache / state | Redis 7.2 (AOF persistence) |
| Monorepo | Turborepo, pnpm workspaces |
| Containers | Docker Compose (dev), Docker multi-stage builds |
- Docker Desktop
- pnpm
>= 9 - Node.js
>= 22 - An Anthropic API key
- A GitHub App (see setup below)
1. Clone and install
git clone https://github.com/your-org/echo-v
cd echo-v
pnpm install2. Configure environment
cp .env.example .envFill in the required values:
ANTHROPIC_API_KEY=sk-ant-...
GITHUB_APP_ID=
GITHUB_APP_CLIENT_ID=
GITHUB_APP_CLIENT_SECRET=
GITHUB_APP_PRIVATE_KEY= # Full RSA PEM, newlines as \n3. Create a GitHub App
- Go to GitHub Settings → Developer settings → GitHub Apps → New GitHub App
- Set Callback URL to
http://localhost:3000/api/auth/callback/github - Enable Repository permissions: Contents (read/write), Pull requests (read/write)
- Disable Webhook active
- Copy the App ID, Client ID, generate a Client Secret and a Private Key
4. Start the stack
docker compose up --build| Service | URL |
|---|---|
| Dashboard | http://localhost:3000 |
| Agent Brain API | http://localhost:8000/docs |
curl -X POST http://localhost:8000/runs/trigger \
-H "Content-Type: application/json" \
-H "X-Internal-Token: $(grep INTERNAL_AGENT_TOKEN .env | cut -d= -f2)" \
-d '{
"cve_id": "CVE-2024-21626",
"repo_url": "https://github.com/your-org/your-repo",
"branch_base": "main",
"dry_run": false
}'The run ID is returned immediately. Watch progress on the dashboard at http://localhost:3000/dashboard.
Set "dry_run": true to test the patch strategy and guardrail check without executing code or opening a PR.
The dashboard renders a live Security Graph — a directed graph of the agent pipeline with animated edges and status-coded nodes.
| Color | Meaning |
|---|---|
| Blue pulse | Stage actively running |
| Green | Stage completed |
| Red | Stage failed or blocked |
| Grey | Idle |
The right panel shows a live Threat Feed (agent event stream) and Agent Runs list with expandable event logs.
Press ⌘K to open the command palette.
The AST checker blocks these patterns in any generated patch:
| Rule | Pattern |
|---|---|
BLOCKED_CALL_OS_SYSTEM |
os.system(...) |
BLOCKED_CALL_SUBPROCESS_* |
Any subprocess.* call |
BLOCKED_BUILTIN_EVAL |
eval(...) |
BLOCKED_BUILTIN_EXEC |
exec(...) |
SHELL_RM_RF |
rm -rf in string literals |
SHELL_CURL / SHELL_WGET |
Network fetch shell commands |
CREDENTIAL_LITERAL |
Hardcoded passwords / secrets / tokens |
ENV_WRITE |
os.environ[...] = ... |
ENCODED_PAYLOAD |
base64.b64decode(...) |
Patches with any BLOCK-severity violation are rejected. The run is marked failed and the violation is written to the audit log.
| Variable | Required | Description |
|---|---|---|
DATABASE_URL |
Yes | PostgreSQL connection string |
REDIS_URL |
Yes | Redis connection string |
AGENT_BRAIN_URL |
Yes | Agent brain base URL |
INTERNAL_AGENT_TOKEN |
Yes | Shared secret for internal API auth |
ANTHROPIC_API_KEY |
Yes | Anthropic Claude API key |
GITHUB_APP_ID |
Yes | GitHub App numeric ID |
GITHUB_APP_CLIENT_ID |
Yes | GitHub App OAuth client ID |
GITHUB_APP_CLIENT_SECRET |
Yes | GitHub App OAuth client secret |
GITHUB_APP_PRIVATE_KEY |
Yes | RSA private key PEM (newlines as \n) |
NEXTAUTH_URL |
Yes | Dashboard public URL |
NEXTAUTH_SECRET |
Yes | NextAuth JWT signing secret |
E2B_API_KEY |
No | E2B sandbox key (falls back to Docker if unset) |
MIT