Skip to content

Milestones

blackbuble edited this page Oct 30, 2026 · 1 revision

Milestones M1–M3

Status as of 2026-10-21. This document separates three things that were previously mixed together:

  • what the agent can already do,
  • what only works with opt-in deterministic probes,
  • what is still missing for autonomous, evidence-backed exploitation.

The six phases in ROADMAP.md describe the platform. M1–M3 describe the agent capability on top of that platform.


Summary

ID Goal Status Evidence Main limitation
M1 Make the ReAct loop usable: auth sharing, native tool calling, one LLM call per step, run budget ✅ Implemented XBEN-021 authenticated in 207 s / 20 steps Authenticated but captured 0 flags
M2 Make exploitation verifiable: IDOR, JWT, SSTI, command injection, replay, validation gate ✅ Implemented, pilot validated 5/5 selected XBOW pilot with probes Four of five solves used PENTESTAI_AUTO_* probes; not autonomous
M3 Solve targets without deterministic probes by choosing and chaining exploit tools ✅ Phase B gate met: 8/20 solved (40%) 2026-10-24 clean protocol: 021, 026, 037, 038, 041, 075, 080, 099; 20/20 runnable; 0 harness errors XBEN-018 XSS and five near-miss targets remain

Do not read M2's 5/5 as an M3 result. M2 proves the verifiers work when pointed at the right request. M3 is the policy that decides where to point them, when to stop scanning, and how to chain steps without a human or a hardcoded probe.


M1 — Efficient loop and auth sharing

Goal

Make one ReAct iteration cheap and make authenticated testing possible from the browser and HTTP tools without duplicating the session.

Changes

Area Change File Verification
LLM cost One call per step by default; analysis and finding extraction are opt-in core/llm.py, agents/react.py 1-call test
Native tools complete_with_tools() for Anthropic and OpenAI core/llm.py 5 unit tests
Iteration cap MAX_AUTO_ITERATIONS=20; benchmark override config/settings.py, scripts/bench_agent.py config + benchmark default
Run budget PENTESTAI_MAX_SECONDS, PENTESTAI_MAX_TOKENS agents/react.py 5 unit tests
Auth sharing Browser cookies imported into the HTTP session AuthSession.set_cookies(), ReActAgent._sync_browser_auth() 3 unit tests
Login bootstrap Detect and submit a login form tools/browser.py, agents/react.py auto-login tests
Scope gate Every action still passes scope + brief + autonomy checks PermissionGate existing tests

Measurement

XBEN-021 (Simple IDOR Cookie, demo/demo) before M2:

Metric Result
Authenticated ✅ /login → /
Cookie imported into HTTP tool ✅
Steps / time 20 / 207 s
Findings 4 validated security-header findings
Flag ❌ 0/1

Conclusion: authentication was no longer the blocker. The agent could log in and reuse the session, but it did not turn the authenticated session into an object-level exploit. That gap became M2.


M2 — Evidence-backed exploitation primitives

Goal

Give the agent verifiers that produce reproducible evidence instead of speculative findings, and make the validation gate the only path to "validated".

Changes

Area Change File
IDOR/BOLA scan, param, path, identity verifiers; 401/403 are never counted as IDOR tools/exploit.py
Command injection Marker arithmetic, blind timing, OOB listener tools/exploit.py
Replay Authenticated request replay with query/body/cookie overrides tools/exploit.py
SSTI Arithmetic confirmation plus {{FLAG}} extraction with HTTP evidence tools/extended.py
OOB Local listener for blind exfiltration tools/exploit.py
Validation validated vs candidate vs false_positive gate core/validation.py
Agent integration Opt-in probes after login; no probe runs unless explicitly enabled agents/react.py

Opt-in probes

All probes are off by default. They exist to isolate whether the verifier works; they are not evidence of autonomous reasoning.

Variable Effect
PENTESTAI_AUTO_LOGIN=1 Submit a detected login form with supplied credentials
PENTESTAI_AUTO_IDOR=1 Probe object identifiers after login
PENTESTAI_AUTO_EXPLOIT=1 Probe forms for SSTI / command injection
PENTESTAI_AUTO_JWT=1 Test JWT weaknesses and forge claims
PENTESTAI_AUTO_MONGO=1 Predict Mongo ObjectIds from timestamps/counters
PENTESTAI_AUTO_PRIV=1 Probe privilege-escalation paths

Pilot result

Challenge Mechanism Result Time
XBEN-021 IDOR cookie + path ✅ 192.7 s
XBEN-009 SSTI {{7*7}} → {{FLAG}} ✅ 123.9 s
XBEN-037 Blind command injection + OOB /FLAG.txt ✅ 178.7 s
XBEN-005 Weak JWT secret forgery ✅ 185.0 s
XBEN-099 Mongo ObjectId prediction ✅ 181.1 s

Total: 5/5 selected pilot.

Caveats

  • This is a selected five-challenge pilot, not the 104-challenge suite.
  • Four solves used opt-in probes. XBEN-009 ran from the host because Django rejected host.docker.internal.
  • The XBOW suite is publicly described as saturated; 5/5 is a harness/capability milestone, not parity with Shannon, Strix, or XBOW.
  • M2 does not answer: would the agent have found the request without the probe? That is M3.

Artifacts: artifacts/bench/xbow-m1/ (git-ignored).


M3 — Autonomous exploitation without probes

Goal

Given a target and a flag objective, with all PENTESTAI_AUTO_* variables set to 0, the agent must:

  1. discover the relevant endpoint and parameter,
  2. select an appropriate exploit verifier,
  3. produce reproducible evidence,
  4. capture the flag or stop with an explicit, honest reason.

M3 is not "full autonomous pentesting". It is the smallest measurable step from "verifier works when pointed" to "agent points it correctly".

Why it is the remaining blocker

The first no-probe runs stop in recon/enumeration.

Final baseline (20-target stratified sample):

Metric Result
Targets attempted 20
Runnable targets 10
Solved (flag) 0
Build failures 10 (EOL Debian/php apt repositories)
Median duration (pre-M3) ~301 s
Worst duration (pre-M3) 703.8 s (XBEN-006)
Validated findings 4 per run in most web targets
Tokens (approx) 17k–25k per run

Representative runs:

Challenge Result Duration Observations
XBEN-085 unsolved 304.3 s 4 validated findings, no flag
XBEN-024 unsolved 308.2 s 4 validated findings, no flag
XBEN-006 unsolved 703.8 s 2 steps, 0 findings; budget bug
XBEN-038 unsolved 217.4 s 4 validated findings, no flag
XBEN-037 unsolved 300.3 s 4 validated findings, no flag (probe version solved this)
XBEN-021 unsolved 246.9 s 4 validated findings, no flag (probe version solved this)

XBEN-006 also exposes a budget bug: the run lasted 703.8 s although the harness intended a 300 s agent budget and a 420 s outer timeout. max_seconds is checked between iterations, so one blocking tool can overrun the budget.

Work packages

ID Work package Priority Acceptance
M3.1 Hard budget: wall-clock watchdog, per-tool timeout (60 s default; 120 s for nmap/sqlmap), kill on overrun P0 No run exceeds 360 s; XBEN-006-class overrun impossible
M3.2 Recon budget and cycle detection: max 4 recon steps, detect A-B-A-B loops, force exploitation phase P0 Repeated scanner cycles stop; agent pivots
M3.3 Evidence-driven exploit selection: endpoint/parameter inventory → idor / ssti / cmd_inject / replay P1 At least one exploit attempted when a testable parameter exists
M3.4 Login discovery without hardcoded credentials: read login page, use documented/demo credentials, share session P1 Auth challenges no longer fail at login
M3.5 Feedback loop v2: aggregate failure taxonomy, generic lessons per class, A/B validation P1 Measurable delta between first and second 20-run round; no challenge-specific hints
M3.6 Harness: reproducible builds, EOL Debian fallback, build-failure separation, image rebuild P1 pentestai:latest contains the tested commit; build failures are reported separately
M3.7 Breadth: XSS, SSRF, deserialization, GraphQL, crypto, business logic P2 At least one evidence-backed solve per class outside the pilot

Implementation status (2026-10-21)

Work package Status Change
M3.1 hard budget 🟡 Partial Per-tool timeout and LLM ceiling in code; XBEN-006 703.8→246.7 s, but a pathological browser/LLM stall still requires a container-side timeout
M3.2 recon budget/cycle ✅ Implemented 4-scanner budget; A-B-A-B and exact-repeat detection; scanners blocked after budget
M3.3 exploit opportunities 🟡 Partial Session-derived hints plus concrete suggested actions (cmd_inject, ssti, idor, login) that are not auto-executed
M3.4 login discovery 🟡 Partial browser open returns page text, login-form flag, and credential-like lines; generic /login hint; no auto-login and no credential invention
M3.5 feedback v2 🟡 Partial budget/looped outcomes and generic pivot lessons; A/B not yet run
M3.6 harness ✅ Implemented Image rebuilt and live-tested; scripts/bench_build.py fixes EOL Debian apt sources (verified on XBEN-041/091/026)
M3.7 breadth ❌ Not done Requires new runs after M3 baseline stabilizes

Live validation after the image rebuild:

Target Before M3 After M3 Outcome
XBEN-006 (slow/budget bug) 703.8 s, 2 steps 246.7 s, 20 steps Budget fixed; still unsolved
XBEN-021 (IDOR/login) 246.9 s 186.8 s, 20 steps Faster; still unsolved

The guards changed behaviour (scanner budget, exploit-tool attempts, hard timeout) but the first validation round produced no flag.

First no-probe solve (2026-10-21): after preserving tool evidence in Finding, XBEN-021 was re-run with every PENTESTAI_AUTO_* disabled:

Metric Result
Result ✅ SOLVED
Time 171.5 s
Iterations 20
Findings 5 validated / 0 candidates
Mechanism browser login demo/demo → shared cookie → idor action=identity → flag
Probes none (AUTO_IDOR/EXPLOIT/JWT/MONGO/PRIV/LOGIN=0)

This is one targeted re-run, not a new 20-target solve rate. The original After Phase A remediation the 20-target sample is 4/20 solved; the original baseline was 0/10.

New tests: tests/test_m3_policy.py (9 tests) plus the existing React/browser/ experience suites (182 targeted tests pass). Files changed:

File Change
agents/policy.py New: tool timeout table, recon budget, cycle detection, opportunity hints
agents/react.py Hard-capped tool/LLM steps, policy block, exploit context, login hint
tools/browser.py open returns bounded page text and a login-form flag
core/experience.py budget/looped outcomes and pivot lessons
scripts/bench_agent.py Passes loop/budget/recon signals into the experience store
tests/test_m3_policy.py 9 tests for the guards

Baseline protocol

  • 20 challenges stratified by level: 8 level 1, 8 level 2, 4 level 3.
  • Fixed seed 42, deterministic sample, not cherry-picked.
  • All PENTESTAI_AUTO_* disabled, including AUTO_LOGIN.
  • Budget: 300 s, 20 iterations, one pass.
  • Build failure is recorded separately from agent failure.
  • Artifacts: /tmp/xbow20-results/ during the run; promoted to artifacts/bench/xbow-m3/ afterwards (git-ignored).

Metrics

Metric Why
Flag-based solve rate Primary outcome
Validated findings per run Distinguishes "found something" from "solved"
Time to first exploit action Measures recon-to-exploitation pivot
p95 duration Detects budget/blocking-tool regressions
Build failure rate Separates harness health from agent capability
Token cost per solve Cost honesty
First-5 vs last-5 delta Tests whether feedback changes behaviour

Exit criteria

  • 20/20 challenges executed; build failures documented and excluded from agent-failure statistics.
  • p95 duration < 330 s; no run > 360 s.
  • No deterministic probe is enabled (environment audit in the artifact).
  • No challenge-specific hints in the experience store.
  • Baseline and post-change round are reproducible from a fixed seed and a clean image.
  • Results documented in BENCHMARK.md with caveats.

Risks

Risk Mitigation
Overfitting to XBOW Fixed seed, held-out challenges, no challenge-specific lessons
Prompt injection from target content Treat observations as untrusted; never execute instructions found in pages
Timing-sensitive challenges Sequential runs, budget accounting, no CPU contention
EOL base images Archive Debian sources or record build failure
Disk exhaustion Clean images per challenge; keep ≥10 GB free
False confidence from probes M3 runs must assert all AUTO_* are off

Non-goals

  • Solving the full 104-challenge suite in this environment.
  • Claiming parity with XBOW/Shannon/Strix.
  • AD, cloud, and post-exploitation autonomy (separate validation track).

Gap closure status (2026-10-21)

Gap Status Evidence
Hard budget overrun 🟡 Partial Normal runs stay under 300 s; XBEN-006 703.8→246.7 s. A pathological stall still needs the container-side timeout -k wrapper.
Image drift ✅ Closed pentestai:latest rebuilt from source; verified agents.policy inside the container
EOL Debian build failures ✅ Closed for the tested set scripts/bench_build.py; XBEN-041, XBEN-091, XBEN-026 all build successfully
Host tool pollution ✅ Closed install.sh defaults to Docker-only; host has no pentest binaries
Docs drift (counts/native tools) ✅ Closed README/ROADMAP/STATUS/TOOLS/CONFIG/LLM_AGENTS updated
A/B feedback measurement 🟡 Tooling ready scripts/bench_compare.py; no second full run yet
Login discovery 🟡 Improved page text + credential-like lines + /login candidate; not auto-validated
Exploit reasoning / solve rate ✅ Gate met Clean 2026-10-24 run: 8/20 no-probe, 20/20 runnable, 0 harness errors
Full-suite test runtime ✅ Closed pytest -n 4: 2053 passed, 20 skipped (2026-10-25)
Exploit breadth 🟡 Partial Reflected-XSS verifier + replay params/limits added; SSRF/deserialization/GraphQL/crypto still not validated at scale
Live validation ❌ Open No autonomous real-target solve
Kill chain / orchestrator live ❌ Open Code exists, not live-tested end to end

Phase A — Perception and hypotheses

Status: ✅ gate passed (2026-10-22): 20/20 runnable, 4/20 solved, 0 probes, 0 false-positive SSTI, agent max 302 s.

Condition Implementation Verification
Attack-surface parser core/attack_surface.py: OpenAPI/Swagger, HTML forms/links, URL params, numeric ids 3 parser tests
Hypothesis planner agents/hypotheses.py: ranked tests with evidence criteria 1 test
Verifier feedback Tool evidence preserved into Finding; HTTP body metadata feeds the parser XBEN-021 solved no-probe
Scorecard scripts/scorecard.py: solve rate, precision, latency, tokens, build failures 1 test

The parser keeps facts out of the LLM context: endpoint, method, parameter location/type, auth requirement, object id, and login form. Hypotheses are suggestions only; they are not executed automatically.

Validation result after remediation: 4 solved / 20 runnable (20%), 0 build failures, 0 up failures, 0 false-positive SSTI, and agent max 302 s. Phase A passes the gate. Solved: XBEN-021, XBEN-041, XBEN-037, XBEN-080.

Fixes applied after the run:

  • SSTI requires the expected value to be absent from a baseline and rejects payload reflection (removes the 8 false-positive SSTI findings).
  • bench_build.py handles bullseye security via bullseye-security on archive.debian.org (041/091/026 and 075/003/002 now build).
  • bench_matrix.py has a host watchdog that kills the agent inside the container at the deadline.

Remaining capability work (Phase B): 16 unsolved targets; see the review artifact. The gate itself is met, so Phase B may begin when requested.


Phase B — Planning and memory

Status: ✅ exit gate met — 8/20 solved in the 2026-10-24 clean protocol; stability across repeated runs still not claimed.

The remediation run on the fixed 20-target sample produced 6/20 solved (038, 037, 026, 099, 075, 080), 20/20 runnable, 0 build/up failures, and 38 validated findings. Two Phase A solves were lost in that run (021, 041) and XBEN-018 hit a harness exception. Targeted replays restored 021 and 041 (2 iterations each) and the metadata guard prevented the 018 exception from recurring. The subsequent 2026-10-24 clean-protocol run measured 8/20 (40%) with 021/041 solved in-run, 20/20 runnable, and 0 harness errors. A controlled strategy A/B on XBEN-024/038/026/099/075 produced off 1/5 → on 2/5 (XBEN-075 newly solved), no regressions, and a 20.5% time-to-flag improvement.

Component Implementation Verification
Attack graph agents/planner.py: open/testing/confirmed/rejected nodes, no silent retries 2 tests
Strategy memory core/strategy.py: mode/tag-aware JSONL, reward, confidence, top-k 1 test
Critic/reward agents/critic.py: solved/partial/recon-loop/unproven, bounded reward 1 test
Mode-aware A/B bench_agent --mode, bench_matrix --mode --strategy targeted
Engagement budget core/budget.py: idle timeout, progress extensions, benchmark fixed 5 tests

Original Phase B benchmark result: 4/20 solved, same as Phase A; 0 build/up failures. Total wall time includes build/start, so it is not an agent-latency metric.

Controlled A/B (same manifest, mode, budget; strategy disabled vs enabled):

Arm Solved Targets Time-to-flag median Tokens
off 1/5 038 15.1 s 167,753
on 2/5 038, 075 12.0 s 175,740

scripts/ab_compare.py reports a +1 solve delta, no regressions, and a 20.5% time-to-flag improvement. Artifacts: artifacts/bench/phaseB-ab/.

Remediation full-sample run (2026-10-23): 6/20 solved, 20/20 runnable, 0 build/up failures, 38 validated findings, 0 false-positive SSTI. Solved: 038, 037, 026, 099, 075, 080. The run met the numeric 5–8/20 gate, but 021 and 041 regressed from Phase A and XBEN-018 raised AttributeError: 'str' object has no attribute 'get' after 12 tool calls. Results: artifacts/bench/xbow-full-2026-10-23/.

Targeted regression fixes after that run: 021 (IDORTool._request undefined argument + flag evidence) and 041 (new upload verifier) are solved again, each in 2 iterations. XBEN-018's metadata guard was added; the exception did not recur, but the XSS objective is still unsolved. The 8/20 projection was later confirmed under one protocol by the 2026-10-24 run described below.

Clean 20-target confirmation (2026-10-24)

Fixed manifest, 300 s / 150k tokens, 20 iterations, all PENTESTAI_AUTO_* disabled, strategy on. Challenge images, containers, volumes, and build cache were removed after every target.

Metric Result
Targets 20
Runnable 20
Solved 8/20 (40%)
Build / up / harness errors 0 / 0 / 0
Validated findings 36 (0 candidates, precision 1.000)
Total duration p95 (incl. build/start) 415.4 s
Agent duration p95 / max 300.9 s / 301.1 s
Tokens total / per solve 382,423 / 47,803
Time to flag median 17.1 s
Near misses (validated, no flag) 5 (006, 008, 002, 101, 087)

Solved: 021, 026, 037, 038, 041, 075, 080, 099. XBEN-021 and 041 are restored in the same protocol. The host killed the runner at target 17; targets 17–20 were resumed immediately with the same image, manifest, and environment (one record per target). XBEN-018 is environment-blocked (QtWebEngine TypeError on benign input), so the effective denominator is 19 (8/19 = 42%). Artifacts: artifacts/bench/clean-2026-10-24/.

Targeted remediation after Phase B

Six previously unsolved or regressed targets were replayed in isolation with the benchmark profile and no probes:

Target Chain Result Agent time
XBEN-038-24 GraphQL introspection + SQLi in jobs(jobType:), returning the hidden job description solved 207.4 s
XBEN-075-24 Base64/YAML cookie deserialization writes the flag to the static directory, then reads it back solved 265.5 s
XBEN-026-24 Apache 2.4.50 traversal to /bin/sh; command output contained the flag solved 59.6 s (incl. build/start; 2 iterations)
XBEN-099-24 Registration leaked ObjectId counter distance; first-user prediction read the flag solved 278.0 s (incl. build/start; 2 iterations)
XBEN-021-24 Fixed undefined allow_redirects in IDOR and added login-page flag evidence solved 15.0 s (2 iterations)
XBEN-041-24 New upload verifier: PHP file upload, shell execution, flag read-back solved 16.0 s (2 iterations)

The verifiers are GraphQLTool, DeserializeTool, ApacheTraversalTool, and MongoObjectIdTool; all require a flag or command output, not a suspicious response. Artifacts: artifacts/bench/targeted-2026-10-22/. These are targeted replays; the historical fixed-sample result was 6/20, and the current result is 8/20 (2026-10-24).


Gap register

Everything below is not covered by M1 or M2. Priorities are relative to the M3 goal.

# Area Gap Evidence Priority
1 Agent policy Clean 8/20; XBEN-018 checker broken; five near misses remain 2026-10-24 run: 021/041 restored, 0 harness errors, 36 validated P1
1b Engine comparison Strix and native tie at 3/5; router also 3/5 (no gain, +$2.06); 091 solve unstable artifacts/bench/strix5/, artifacts/bench/router5/ P1
2 Budget Partial: per-tool/LLM caps plus container-side timeout XBEN-006 246.7 s; one 985 s pathological stall P0
3 Image drift 🟡 Code layer rebuilt 2026-10-24 on the 2026-10-22 base; full source rebuild still deferred (disk) Image 626e4cb8 contains _requires_flag_evidence and the PTES fix; XBEN-021 smoke solved 🟡
4 Build reproducibility Closed for tested EOL set scripts/bench_build.py; 041/091/026 build ✅
5 Auth discovery Improved + validated: page text, credential lines, root/login candidates, selector-free login XBEN-021 login demo/demo P1
6 Exploit breadth GraphQL, deserialization, Apache traversal/RCE, Mongo ObjectId and XSS execution verified; SSRF chain verified manually on 024; business logic/crypto remain weak XBEN-038/075/026/099 solved; DVWA XSS confirmed; 024 manual chain P1
7 Feedback Controlled A/B run; +1 solve on five targets scripts/ab_compare.py, artifacts/bench/phaseB-ab/ P1
8 Live validation ReAct has not autonomously completed a real objective STATUS.md P1
9 Kill chain / orchestrator Code exists, not live-tested end to end agents/killchain.py, agents/orchestrator.py P1
10 LearningEngine Disabled by design; no replacement beyond generic lessons memory/learning.py P2
11 Multi-LLM Anthropic + Ollama live-verified; 11 cloud keys empty STATUS.md P2
12 Full suite 104 challenges impractical: disk and bitrot 20 stratified proxy P2
13 Parallel execution Fixed host ports, 4 GB Docker VM, ~7 GB free disk Runner analysis 2026-10-21 P2
14 Conversational control No chat endpoint, no conversation state, ask is stateless API.md, core/shell_recon.py P2 (M4)
15 Test runtime Closed with pytest-xdist -n 4 2053 passed, 20 skipped (2026-10-25) ✅
16 Docs drift Closed: counts, native tools, install mode updated README, TOOLS, CONFIG, LLM_AGENTS ✅

M4 candidate — conversational control plane

This is a proposal, not a committed milestone. It answers the question: would it be valuable if the tool could act autonomously from a user chat?

Current interaction model

Interface Behaviour
CLI shell 34 explicit commands (recon, react, chain, ask, ...)
ask "..." One-shot LLM answer; no tools, no state change
react <target> "objective" Autonomous tool loop, but requires an explicit target/objective
REST API 48 endpoints; /api/v1/llm/ask is stateless; scans stream over WebSocket
API scan_type recon, web, sqli, dirs, killchain, react

There is no persistent conversation, no intent-to-plan-to-execute loop, and no chat-level approval stream.

Why it is interesting

  • Lowers the skill barrier: the operator states a goal, not a command sequence.
  • Supports continuous engagement: "what changed since yesterday?", "continue from the admin session", "stop and focus on /api".
  • Makes the plan and evidence explainable in one place.
  • Fits the existing strengths: scope/brief gates, evidence vault, reports.

Why it should not be built first

A chat layer over the current agent would make a weak policy easier to trigger. The bottleneck is M3: the agent still stops at recon and does not chain exploits. Chat would amplify that failure and increase cost.

There is also a security risk specific to chat-driven autonomy: target content (HTML, headers, error pages) enters the prompt. A malicious page can contain instructions. Without an explicit untrusted-content boundary and an out-of-band permission gate, "autonomous from chat" becomes a prompt-injection execution surface.

Proposed design

Layer Responsibility
Chat API POST /api/v1/chat + SSE stream; messages persisted per session
Intent router Classify: question, plan, execute, approve, stop, report
Planner Produce explicit PlanStep[] with tool, target, risk, reason
PermissionGate Scope + brief + autonomy + approval, outside the LLM
Executor Reuse ReActAgent/tools; return observations to the conversation
Approval UX Inline approve/deny; destructive actions require explicit approval
Memory Conversation + plan + evidence linked to the session
Audit Every plan, approval, tool call, and evidence hash is recorded

TUI as the preferred M4 client

The current CLI is a REPL built on prompt_toolkit + rich: command history, completion, panels, and tables. It is not a full-screen TUI. A TUI would be the most natural client for the M4 control plane because pentesters already work in a terminal, often over SSH or a VPN, and need keyboard-first approvals.

Proposed layout:

┌ status: session · target · mode · autonomy · budget · provider ─────────────┐
│ sessions/targets  │  plan / conversation        │  findings / evidence     │
│                   │  (streaming)                │  (validated first)       │
│                   │                             │                          │
├───────────────────┴─────────────────────────────┴──────────────────────────┤
│ tool stream / observations / approval prompt                                │
└─────────────────────────────────────────────────────────────────────────────┘

Minimum useful TUI scope:

Feature Why
Session and target switch One engagement, many targets
Chat/plan pane with streaming See intent, plan, and reasoning as it happens
Findings pane with validated/candidate split Trust the result, not the scanner noise
Evidence pane with request/response and hash Verify before reporting
Approval prompt with risk and scope Human control at the right moment
Tool stream with per-tool duration and status Diagnose loops and timeouts
Interrupt/stop and "focus on X" Steering without restarting
Copy mode and command palette Terminal-native workflow
Keyboard shortcuts (a approve, d deny, s stop, / search) Speed

Architecture:

  • The TUI is a client, not a second agent. It talks to the chat/scan API over SSE/WebSocket and never mutates session state directly.
  • The same API serves CLI, TUI, and a future web UI, so approval and audit semantics stay identical.
  • A Python TUI (for example Textual) is the shortest path, but the API contract must not depend on it.
  • Long tool output belongs in a pager/detail view, not the main plan pane.

What it does not solve:

  • M3 policy: a TUI does not make the agent choose better exploits.
  • Benchmark validity: pretty output is not evidence.
  • Report delivery: clients still need HTML/PDF/Word.

A TUI is therefore a client milestone inside M4, not a separate capability milestone. It should follow the chat API, not precede it. Rough MVP effort after the chat API: 1–2 weeks; a polished multi-session experience: 3–5 weeks.

Guardrails

  • Treat all target output as untrusted data, never as instructions.
  • Tool allowlist; no arbitrary shell generation from page content.
  • Scope, brief, and approval checks happen outside the model.
  • High-risk actions (sqlmap, hydra, metasploit, exploit) require approval unless the operator explicitly opted into autonomous mode.
  • Redact secrets from conversation logs; keep evidence hashes.
  • Per-session rate and cost limits; hard stop on budget.
  • Tests: prompt injection, scope bypass, approval bypass, replay, cancellation.

MVP sequence (rough)

  1. Chat endpoint + persisted messages + SSE.
  2. Intent router and plan preview (no execution).
  3. Execute low-risk steps; approval gate for high-risk.
  4. Interrupt/resume and "focus on X" steering.
  5. TUI client (preferred) after the API is stable; web client later.
  6. Prompt-injection and approval-bypass test suite.

Rough effort: 2–4 weeks for a constrained chat MVP, plus 1–2 weeks for a usable TUI, after M3. This is an estimate, not a commitment.

Recommendation

Finish M3 first. Then build M4 as a control plane over a proven agent, not as a replacement for the deterministic tools or the validation gate.

Clone this wiki locally