Skip to main content

redveil-ui

Self-hosted dashboard for redveil scans. Burp-style workspace, real findings, zero cloud dependency.

PyPI version Python License: Proprietary Tests redveil

pipx install redveil-ui
redveil-ui init
redveil-ui start
# open the URL printed by init (default http://127.0.0.1:<port> —
# port may differ if 8000 was taken; check your config with:
#   grep '^port' ~/.redveil-ui/config.yaml

⚠️ Before you start — this runs on YOUR network

redveil-ui is 100% local. No data leaves the host it runs on. The app is bound to 127.0.0.1 by default — it is not reachable from other devices on your network unless you change the config. If you do expose it, every scan it launches is sent from your IP address against the target you specify. If the target isn't yours, or you don't have explicit written permission to test it, the legal and ethical responsibility is yours — not the maintainers'.

Because the dashboard is self-hosted, the security perimeter is also yours: who can reach the instance, what targets you queue, and whether destructive checks are enabled. Treat it like any other local service with a security boundary.

The Probe Builder's "Custom payload" mode has a two-gate confirmation (Gate 1 + Gate 2, both required). That's not UI friction for its own sake — it's because custom payloads sit outside the curated set of redveil's built-in checks, so the framework can't pre-validate them for safety. The two gates exist so you have to pause and confirm what you're about to send.

See DWYOR.md for the full statement.


what you get

The package bundles a FastAPI backend, a Next.js 16 SPA, and the redveil library under one uvicorn process on one port. One install, one config file, one URL to remember.

The screenshots below are taken against this exact package, served by redveil-ui start, with a seeded scan + finding to make the data realistic. Click any of them to view full-size.

1. Targets — register a host before you scan it

Targets list

The starting point. Every scan targets a row in this list. Each row carries the URL, an optional human label, and the YAML scope block that the orchestrator hands to the redveil library's ScopeController. Add a target once, scan it many times against different profiles.

The New target button (top right) takes you to the combined target + scan form — see "New Scan" below.

2. New Scan — target + scan config in one form

New Scan form

This is the primary action of the dashboard: register a target and configure the scan in a single form. Fields:

  • URL (required) — validated client-side for http(s) scheme, blocked from cloud-metadata endpoints (169.254.169.254 and metadata.google.internal).
  • Name (optional) — operator-friendly label.
  • Scope YAML (optional) — if omitted, the auto-allow scope from scope_check.py lets the target's host through; otherwise a strict allowed_hosts / allowed_paths block is enforced at scan creation.
  • Profilepassive (default, read-only recon), low_impact (non-destructive probes), active (exploitation-grade; needs allow_destructive).
  • Destructive level ceilingL1 through L6. The framework refuses any scan where level >= L3 and allow_destructive is false.
  • Allow destructive — opt-in unlock. Default false. Without it, even L3+ checks are denied per-action at runtime.
  • Gate modenon_interactive (default, auto-approve and log), strict (auto-deny MEDIUM+), interactive (v2, currently disabled).
  • Max requests (optional) — hard cap. The form warns if you pick active with a budget below 1500 (Time-Based SQLi worst case 640 + Command Injection worst case 1190).

Submitting creates the target row and starts the scan in one POST pair; the page redirects to the new scan's detail page where progress streams in live.

3. Scan Detail — live progress, findings, controls

Scan detail

The high-traffic page during a scan. Three things stream in:

  1. Status pill (top): pendingrunningcompleted / failed / cancelled.
  2. Findings list (mid): populates as the orchestrator emits them. Each row has severity, confidence, title, endpoint, and a View link.
  3. Event log (right rail): per-action decisions from the ActionGate (auto-approve, denied, etc).

SSE connection: GET /api/scans/{id}/stream emits one event per orchestrator action with : keep-alive heartbeats every 15s. The Python backend uses a per-scan pub-sub (redveil_ui/api/event_bus.py) so the orchestrator can run independently of any open SSE clients — closing the tab does not cancel the scan.

4. Scan History — past runs at a glance

Scan History

List of every scan the operator has run, ordered newest first. Filters: status (all / running / completed / failed / cancelled) and free-text search across target URL + name. Click any row to go to that scan's detail page.

Stat tiles at the top show total scans, running count, and 7-day finding count. Empty state prompts the operator to start a new scan.

5. Dashboard — entry point

Dashboard

Recent activity, stat tiles (total scans / active targets / 7-day findings), and quick links to create targets or review history. Sidebar nav gives one-click access to every section.

6. Target / Site Map — per-target endpoint inventory

Target sitemap

Drill-down view for a single target: every endpoint the orchestrator discovered during scans, grouped by folder, with per-endpoint finding counts and severity histograms. Pulls from GET /api/targets/{id}/sitemap.

7. Evidence Log — every request/response captured

Evidence Log

All Evidence objects written by the orchestrator during scans. Each row has the timestamp, endpoint, HTTP method, status code, body length, and a short body excerpt. Filterable by method, check_id, and status_min/status_max. Click a row to expand the full request/response.

This is the same evidence that powers the ReplayEngine and the confidence = oracle × (1 + log2(distinct_dims)) × weight − env_penalty − uncertainty scoring in the underlying redveil library.

8. Finding Detail — investigate one finding

Finding detail

For a single finding: severity, confidence, CWE / OWASP tags, technical_explanation (why the orchestrator marked this as a finding), and remediation (what to do about it). The Replay button runs the captured ReplayRecipe N times to verify reproducibility — see Replay below.

9. Replay — verify reproducibility

Replay

Takes the captured ReplayRecipe (request method + URL + body + headers) and re-issues it N times. If the timing-signal reproduces consistently, the finding's confidence is corroborated; if it flakes, the finding is demoted. The redveil library's ReplayEngine runs the samples; this UI just configures sample count and shows the verdict.

If the original finding has no replay_recipe (some checks don't capture one — that's documented in the model), the Replay button is hidden and a "Replay not available" callout shows why.

10. Probe Builder — manual targeted probing

Probe Builder

Operator-initiated probes, separate from the automatic checks. Two modes:

  • Preset — pick a built-in check (e.g. sqli-time-based) and the client fetches its payload set from GET /api/probes/payload-sets. Select by index, no string input.
  • Custom — write your own payload string. The form requires confirmed_dwyor: true in the POST body and the endpoint enforces this with HTTP 403 if missing — the two-gate DWYOR confirmation (Gate 1 expand to acknowledge, then Gate 2 type-to-confirm). This is the "outside curated checks" path mentioned in the warning at the top of this README.

The Probe Builder reuses the same HttpClient + ScopeController as the automatic checks, so the same scope/destructive-level rules apply. A custom probe that violates scope is rejected by HttpClient with ScopeViolation before any request is sent.

11. Plugins — 19 checks at a glance

Plugins

Read-only list of every check plugin discovered from the installed redveil library via its entry_points = redveil.checks metadata. The list comes from GET /api/checks. This is the same source the orchestrator loads at scan start, so a 19-check install of redveil shows 19 cards here, dynamically — no static copy.

12. Decoder

Decoder

Multi-format decode (base64, hex, URL, HTML entities, JWT split). Reads a string, tries every decoder, shows the output. Frontend is a thin wrapper around redveil.knowledge.Decoder.

13. Comparer

Comparer

Side-by-side evidence diff for two captured requests. Calls redveil.knowledge.Comparer to diff structured fields (status code, headers, body) so the operator can spot what changed between two runs of the same endpoint.

14. Token Entropy

Token Entropy

Shannon entropy + per-token analysis. POST /api/entropy/analyze takes a string and surfaces both the overall entropy score and the per-segment breakdown — useful when reviewing captured session tokens, JWTs, or other opaque strings that the operator wants to fingerprint.

15. Settings — the live config, not a hardcoded page

Settings

Reads the same ~/.redveil-ui/config.yaml that redveil-ui init wrote and the server reads at startup. Every field shown here is the value the running process is actually using (host, port, data_dir, reports_dir, gate_mode, max_destructive_level, allow_destructive). No fake / hardcoded values.


why redveil-ui vs the CLI

redveil-ui (this package) redveil CLI Burp / Nessus / enterprise platforms
Interface Browser dashboard, one port, real-time SSE Terminal, exit code, JSON output Heavy Java/Electron client, often paid
Hosting 100% local, 127.0.0.1 by default Your shell Cloud / licensed server
State SQLite at ~/.redveil-ui/data/ Per-run directory under reports/ Project server, often remote
Probe library Same 19 checks via the installed redveil library Same 19 checks Different ecosystems
Replay One click in the UI redveil replay <report-dir> Manual via Intruder/Comparer
Cost Free, Proprietary, self-hosted Free, MIT, self-hosted $400+/yr per seat
Best for Solo operators running scans on their own schedule CI / scripted / automated Teams with budget + need for shared state

If you only run scans from cron or CI, the CLI is enough. If you want to sit at a browser while a scan runs, see findings populate, dig into evidence, and replay individual results, this is the interface.


architecture

Browser (port 8000)
   │
   │ HTTP / SSE
   ▼
Uvicorn :8000 (single process)
   │
   ├─► FastAPI app (redveil_ui.api.main)
   │     ├─► /api/* routers
   │     │     ├─ /api/targets, /api/scans, /api/findings
   │     │     ├─ /api/checks, /api/probes/*
   │     │     ├─ /api/entropy/analyze
   │     │     └─ /api/scans/{id}/stream  (SSE)
   │     ├─► redveil_ui.api.event_bus (per-scan pub-sub for SSE)
   │     └─► Static SPA fallback: serves ui/frontend/out/{route}.html
   │           └─► React Router hydrates the rest
   │
   └─► redveil_ui.scanner (orchestrator)
         │
         │  imports from `redveil` (installed lib, version pinned ≥1.9.6)
         ▼
       redveil.orchestrator.run(scan)
         → redveil.http.HttpClient (with ScopeController)
         → redveil.plugins.check_registry
         → redveil.validation.ActionGate
         → redveil.reporting.markdown.write_report
         → redveil_ui.api.event_bus.publish (for SSE)

One port, one process, one SQLite file. The frontend is a static export served by the same uvicorn. There is no separate API server, no reverse proxy, no Redis, no Postgres.


requirements

  • Python ≥ 3.11
  • redveil ≥ 1.9.6 (auto-installed as a dependency)
  • ~80 MB disk for the wheel + transitive deps in a fresh venv
  • A free TCP port (default 8000; the init command picks the next free port if 8000 is taken)

redveil must be importable as import redveil — the dashboard will fail-fast at startup if it isn't.


deployment modes (0.2.0)

Localhost (default)

Bind 127.0.0.1, no auth, single operator — the 0.1.x behavior, unchanged. Nothing to configure.

LAN opt-in

Expose the dashboard to your local network. Three steps:

  1. Set a non-loopback bind: redveil-ui init --bind 0.0.0.0 (or edit host: in ~/.redveil-ui/config.yaml). init shows a Y/n warning and records your confirmation in security.log.
  2. Set an API key. init generates one automatically (rvui_…, shown once — save it). Three storage locations are honored, first match wins: REDVEIL_UI_API_KEY env var → ~/.redveil-ui/.api_key file (mode 0600) → auth.api_key_hash in config.yaml.
  3. Start. The server refuses to start (AuthConfigError, exit 1) on a non-loopback bind without a key in any of the three locations.

Auth rules on LAN:

  • Destructive actions require auth — creating an active-profile or L3+ scan, running a custom probe, deleting a target. Without a valid cookie or X-API-Key header these return 401.
  • Passive reads stay open — viewing the dashboard, listing scans and findings, /healthz.
  • Browser logs in via POST /api/auth/login (HttpOnly cookie, SameSite=Strict, 24 h TTL; Secure is set automatically when the request is HTTPS or arrives via a TLS-terminating proxy).
  • CLI / curl sends -H "X-API-Key: rvui_…".
  • Rotate the key with redveil-ui auth rotate-key — this instantly invalidates every existing session.
  • Rate limits apply per IP: 60 req/min on every route by default (override with REDVEIL_RATE_LIMIT_DEFAULT, e.g. 600/minute; set to 0/minute to disable), 5 req/min on login (brute-force damping). X-Forwarded-For is honored only from trusted proxies (REDVEIL_TRUSTED_PROXIES, default loopback) so a LAN client cannot rotate its apparent IP to dodge the per-IP bucket.

Plaintext limitation: without a reverse proxy the session cookie travels unencrypted on the LAN. That is acceptable on trusted home/lab networks and NOT acceptable on public WiFi, conferences, or shared LANs.

Multi-user / public network (out of scope)

redveil-ui is a single-operator tool. For team or untrusted-network deployments, put a reverse proxy in front (Caddy or Traefik terminating TLS, plus Authelia/Authentik for identity) and keep redveil-ui bound to loopback — its own auth is then bypassed entirely and the proxy handles access control.


status & roadmap

0.2.0 adds reliability hardening, opt-in LAN auth, scan control, and an audit trail on top of the 0.1.x feature set:

  • SQLite WAL mode + busy_timeout=5000 + retry-on-lock on write-heavy paths, and a startup recovery sweep that fails orphan 'running' scans from a previous crash.
  • LAN auth (opt-in, fail-closed) as described above, plus /api/auth/login + /logout.
  • Scan control: POST /api/scans/{id}/start and POST /api/scans/{id}/cancel, with a new cancelled terminal status surfaced across the API, SSE stream, and dashboard.
  • Audit log: append-only audit_log table + GET /api/audit + redveil-ui auth audit-rotate (90-day retention).
  • Security headers (CSP, nosniff, DENY, Referrer-Policy, Permissions-Policy) on every response, both modes.
  • Findings page with the false-positive toggle that 0.1.x deferred.

known limitations (roadmap, not blockers)

  • max_requests UI in scan list — server-side cap (Field(gt=0, le=100000)) is enforced; per-scan row display in /scans doesn't surface it. Cosmetic.
  • Empty-state contract — list endpoints return [] for empty DB; /api/scans/{id}/evidence returns 404 (not []) for an unknown scan id. UI handles both. Maybe align in 0.3.0.
  • e2e_lab + negative_testing tests are backend integration tests shipped with the redveil library. They run cleanly (8 + 4 = 12 pass) and are listed in the library's CI, not the dashboard's acceptance criteria.

security posture (relevant for review)

The redveil-ui API applies the same safety checks as the redveil CLI:

  • URL safety (always-blocked at the schema layer): file://, ftp://, javascript:, data:, 169.254.0.0/16 (incl. AWS IMDS), 168.63.129.16 (Azure WireServer), metadata.google.internal (GCP). RFC1918 + loopback are allowed but must be in the target's allowed_hosts scope.
  • Scope check runs synchronously at scan creation. Out-of-scope scan → 403, scan never starts.
  • Destructive level: L3+ requires allow_destructive: true. Refusal is 422 with a clear message.
  • Probe Builder requires confirmed_dwyor: true in the body, validated server-side.
  • YAML parse failure in scope_yaml is a hard error (rejected with 422), not a silent fallback to "allow everything".
  • Loopback default: server binds 127.0.0.1 only. LAN exposure requires a config edit.

see also

  • redveil — the underlying scanning library. redveil-ui is a thin operational layer over it.
  • FitzyPrjkt/Redveil-UIredveil-ui package source, build config, and PyPI release artifacts.
  • FitzyPrjkt/Redveil — underlying redveil scanning library (CLI) that redveil-ui depends on.
  • USER_GUIDE.md — detailed walkthrough of CLI install + scan invocation.
  • CONTRIBUTING.md — how to add a new check plugin.
  • SECURITY.md — full safety model and how to report issues.

license

Proprietary, NOT open source. See LICENSE.

What you can do without asking:

  • Self-host the unmodified redveil-ui package for your own use.

What you cannot do without written permission from the copyright holder:

  • Redistribute, mirror, or ship the package through any channel other than the official PyPI release.
  • Modify, adapt, translate, or create derivative works.
  • Rebrand, repackage, or remove the copyright / license notices.
  • Use the names redveil, redveil-ui, or any confusingly similar name on derivative products.
  • Commercial use, sale, or sublicensing.

If you want a different arrangement (commercial license, derivative work, OEM bundling, etc.) — contact the copyright holder.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

redveil_ui-0.2.0.tar.gz (1.6 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

redveil_ui-0.2.0-py3-none-any.whl (812.8 kB view details)

Uploaded Python 3

File details

Details for the file redveil_ui-0.2.0.tar.gz.

File metadata

  • Download URL: redveil_ui-0.2.0.tar.gz
  • Upload date:
  • Size: 1.6 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.5

File hashes

Hashes for redveil_ui-0.2.0.tar.gz
Algorithm Hash digest
SHA256 2b5f36ea81e18f5d6484202d20c23edd663e65761f1a37a0680c9e838ce1e42a
MD5 f7186f8b79346476dacc88b1eba27d46
BLAKE2b-256 3df9d765e446a9d95ebdf64fdc22f11346d97a7a22c02d28931b5abe34bdd289

See more details on using hashes here.

File details

Details for the file redveil_ui-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: redveil_ui-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 812.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.5

File hashes

Hashes for redveil_ui-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 33adc867fdb86140383cb8e1c7e6205ccf1971de36f2c15eef61d9d3bab040a7
MD5 20936cb604681a48b7811bf66c451e5e
BLAKE2b-256 6ae76fd03bd7ce5ce19f7473bb92c9aaecf2c65ee99d9e34bfc49dba2f7b09cd

See more details on using hashes here.

Release history Release notifications | RSS feed

0.3.0

2 files

This release

0.2.0 This release

2 files

0.1.6

2 files

0.1.5

2 files

0.1.4

2 files

0.1.3

2 files

0.1.2

2 files

0.1.1

1 file

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page