Detection benchmark

A self-scan against our own product tells you we test ourselves; it doesn't tell you the engine works on applications we didn't build. So we run Aegis against public, intentionally-vulnerable apps and publish exactly what happened — including what it missed. It's reproducible: the harness is in our repo and you can run it yourself.

First published target below is OWASP Juice Shop. crAPI, WebGoat and a custom multi-tenant app follow — all runnable from the same harness.

Target: OWASP Juice Shop

The widely-used, deliberately-insecure OWASP web app. Run on 2026-08-18 against the current image. Juice Shop is an Angular single-page app, so — as a real user would — we supplied its documented REST API surface (Aegis supports OpenAPI import for exactly this; see Known limits). Only the non-destructive, read-only active suite was run.

MetricResult
API endpoints tested4 (seeded REST surface)
Requests sent86 (62 active probes)
Wall-clock3.8 seconds
Findings14 — 1 critical, 3 high, 2 medium, 6 low, 2 info
False positives0

What it found (all true positives)

FindingSeverityClass
Boolean-based blind SQL injection (repeatable true/false differential)CriticalCWE-89
Exposed .env file (×3)HighCWE-538
Exposed config fileMediumCWE-538
Missing Content-Security-Policy headerMedium
Wildcard CORS policy (×4 endpoints)LowCWE-942
Missing Referrer-Policy / Permissions-PolicyLow
Server advertises state-changing HTTP methodsInfoCWE-749

The headline is the critical SQL injection: Juice Shop's search API is injectable but returns JSON data, not a SQL error, so an error-based check would miss it. Aegis's boolean detector sends a matched always-true / always-false pair and confirms a repeatable, condition-driven change in the response (here: a true condition returned ~21,500 bytes of results versus ~30 for false) that a benign control input did not reproduce.

False positives: zero

Every finding is real. Notably, on a non-injectable probe the SQL-injection check produced a clean empty result and correctly stayed silent — low false-positive behaviour matters as much as detection.

Browser-based discovery (new)

The run above seeded the API surface by hand because Juice Shop is an Angular single-page app — its endpoints only exist once JavaScript runs. We've since added a headless-browser discovery engine: Aegis drives a real Chromium, executes the app's JavaScript, follows client-rendered routes, and observes every fetch/XHR/WebSocket the app makes — then hands that surface to the attack engine. It navigates and observes only (no form submission, no state-changing clicks), so it's safe on production. Measured on the same Juice Shop image, browser discovery on vs. off:

MetricServer-HTML crawl only+ Browser discovery
Endpoints discovered127
— from observed fetch / XHR017
— client-rendered routes09
Active probe requests sent8329

Executing JavaScript took the tested surface from a single endpoint to 27, and let the active suite send 329 probes instead of 8 — on an app where a server-HTML crawler sees almost nothing. This runs on the authenticated tier; importing an OpenAPI spec still adds any surface behind a write action.

Known limits (stated plainly)

  • Single-page apps: a headless browser now executes JavaScript and discovers client-rendered routes and observed API calls (see above). It navigates and observes only, so surface reachable only after submitting a form or triggering a write is still best covered by importing your OpenAPI spec (supported in-product) — the two sources are merged.
  • One target so far. This is Juice Shop only. It is not a claim about detection rates across all apps; crAPI, WebGoat and a custom multi-tenant app are next, published the same way.
  • Not every class applies to every app. Juice Shop exercised SQLi, headers, CORS and exposed files here; other targets exercise IDOR/BOLA, SSRF, XXE and business-logic differently.

Reproduce it

The harness (tools/benchmark.py) runs Aegis's real plugins through a real scan runtime and emits the metrics above as JSON — no invented numbers. In short:

BASE="docker compose -f docker-compose.yml -f tools/docker-compose.benchmarks.yml"
$BASE up -d juiceshop
$BASE run --rm -T -e TARGET_URL=http://juiceshop:3000 -e INCLUDE_BROWSER=1 benchmark

Full instructions and target list are in tools/BENCHMARK.md. See also our self-test (we test ourselves) and the full test catalogue.