Root cause of "can't send prompts while a run streams": /api/exploit
spawned a plain `neurosploit run ...` subprocess, and that CLI path
(run_mode() in main.rs) never reads stdin - it only waits on the task or
Ctrl-C. The ONLY thing in the harness that keeps accepting input while an
engagement streams is the interactive REPL's background-run loop. So:
- New startJobViaRepl(): for mode run/whitebox/greybox, spawns a bare
`neurosploit` REPL session and scripts it via stdin (/target or /repo,
/model, /sub, /mcp, /votes, /chain, /recon, /focus, /objective,
/scope-out, /creds, /only <agents> or /only clear, then /run) instead
of building CLI args. Same underlying pipeline, same tagged output
lines, so all existing parsing (findings/phase/progress/runId) works
unchanged. host/aitest/skills modes stay on the old one-shot
startJob() - they need onboarding's scope picker, an interactive
arrow-key menu that silently skips itself over a piped stdin, so they
can't be scripted this way.
- New POST /api/exploit/:id/input writes a line to the session's stdin -
natural language, /status, /continue, anything the REPL accepts - and
the live run view grows a "send prompt" box (in the Activity log tab)
for it, shown only when the job reports interactive: true.
- Stop, for an interactive job, now sends the REPL's own graceful
'/stop\n1\n' (validate what's found, then report) instead of SIGINT -
the REPL's own input loop has no signal handler, so SIGINT there would
just kill the process outright and skip the report step. Non-
interactive jobs still get SIGINT (run_mode() does catch that).
- 'done' can no longer be process-exit only: an interactive session stays
open after the engagement finishes (for /report, /continue, another
/run), so ingestLine() now also flags done from the same "phase
complete" content signal it already used for the phase field.
Verified end-to-end: started an interactive job, confirmed
`interactive: true` and a captured runId, sent /status and /agents mid-
and post-run over the new /input endpoint (both accepted, session stayed
alive and responsive after completion), and confirmed a non-interactive
run is unaffected.
Also: the missing "Activity log" tab a screenshot showed for a "running"
engagement was the sidebar's detail-view fallback (2 tabs, no log) for a
run whose Job object no longer exists in server memory - it happens when
the Node process gets restarted while a spawned neurosploit child is
still alive underneath it (an orphan from testing across many redeploys
this session, not a code bug); the live view itself always had the tab.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0129WdYHccPsH27k5GGuwijd
/only <agent,...> (app/src/repl.rs): the REPL had no way to pin an exact
agent set the way the CLI's --only flag does - Session gained a `pinned`
field, wired into RunConfig in both start_background() (the live
background-run path) and the blocking run() fallback. Needed so the web
console's exploitation jobs can drive a real interactive REPL session
(for live input while a run streams) without losing lead-pinning, which
only existed as a CLI flag until now. Also usable directly from a
terminal REPL session.
HTML report (crates/harness/src/report.rs, html()): rebuilt to match the
Typst PDF template's design (templates/report.typ) instead of its own
inconsistent styling - violet brand accent, an asset table, a 5-box
executive-summary grid (all severities, zero-count included, matching
Typst's grid exactly), a Vulnerability Summary table, and severity-
left-bordered finding cards with a compact field grid (Criticality /
Status / OWASP-CWE / Confidence / Location / Agent / Auth context) before
Description-Impact / Proof of Concept / Evidence / Remediation - same
field order and labels as the Typst template. Dropped the Mermaid
attack-path/kill-chain section entirely (the web console's live
Generative Attack Path Chaining graph covers that now, interactively).
Also tidied two pre-existing formatting quirks while in there: OWASP/CWE
left a dangling " · " when CWE was empty, and the confidence cell said
"<votes-string> votes" even when the votes field already contained a
compound descriptor like "1/1 · receipt_missing".
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0129WdYHccPsH27k5GGuwijd
- Agent library table was stale (196/12/78/17 = 303 total, missing the
infra/chains/ai categories entirely). Corrected to the real counts
(245/78/30/34/23/13/12 = 435), matching the "MD Agents-435" badge and
neurosploit agents output.
- Provider badge said 16; the harness actually ships 18 (litellm and azure
were missing from the README's provider table and the API-key export
block). Added both.
- Web console section was a 3-line stub written before most of the feature
was built. Expanded to cover the 5-step wizard, the lead board's bulk
select/category toggles, custom-lead-generates-a-real-agent, the live
run view's Generative Attack Path Chaining graph and finding/PoC detail,
the Auth & Keys menu, and F5 persistence - with links to web/API.md and
web/README.md.
- Select all / Clear all buttons in the Leads step toolbar - respects the
current search filter, so filtering to "sql" then Select all only pins
those, not all 412 leads. The per-category master switch (already
select/deselect-all for that category, indeterminate when partial) was
the only bulk control before; this adds the "everything" case.
- '+ Custom lead' now generates an ACTUAL specialist-agent markdown file
(agents_md/vulns/custom_<slug>.md, same format every other agent uses)
via the claude CLI on the operator's Anthropic subscription
(claude-opus-4-8 by default - matches the harness's own default model),
instead of folding free text into --focus. The new lead is immediately
selectable and pinnable via --only like any other agent; verified the
Rust harness's own agent loader picks it up (agent count went 435 -> 436,
neurosploit agents confirmed it).
Two things found and fixed while wiring this up:
- the skip-permissions flag gave the model file/bash tool access, which
made it try to write the file itself and narrate doing so instead of
just returning text. Dropped the flag (pure text completion needs no
tools) and told it explicitly not to use any.
- Even so, defensively strip anything before the first '# ' heading
before saving, in case a model still prepends commentary.
Falls back to the old free-text-focus behavior if generation fails
(claude not installed/logged in, malformed output, timeout) so the
operator's intent isn't lost.
- New "Custom Leads" category, shown first, so generated leads have a
visible home instead of landing in the catch-all "Other" bucket.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0129WdYHccPsH27k5GGuwijd
impact and business_impact often carry identical text (both ending with the
reporter's 'Identified and validated by NeuroSploit...' footer), and the
modal concatenated them verbatim — the boilerplate line rendered twice, and
whenever the two fields matched, so did the whole paragraph.
- Strip the attribution sentence out of impact/business_impact/remediation/
evidence wherever it appears; surface it once, at the bottom of the modal,
instead of embedded per field.
- Skip business_impact entirely when it's identical to impact (the common
case) instead of printing the same paragraph twice.
- Split rendering into codeBlock() (endpoint/payload — monospace, looks like
what it is: a request/curl) and proseBlock() (description/impact/
remediation — a readable paragraph, not a code box).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0129WdYHccPsH27k5GGuwijd
Node/edge colors now use the same --sev-*-fg / --surface / --text / --border
CSS custom properties as the rest of the console (set via inline style=
attributes, since SVG presentation attributes don't resolve var()) — the
graph reads correctly in light mode instead of always rendering as a
dark canvas.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0129WdYHccPsH27k5GGuwijd
The 'Generative Attack Path Chaining' tab previously showed kill-chain
stages as stacked cards in columns — with 1 finding (the common case
early in a run) it looked like an empty list, nothing like an attack
graph.
Rewritten as an inline SVG node/edge graph on a fixed-dark canvas
(matches attack-graph tools like NodeZero regardless of the app's own
light/dark theme — bright severity colors read better against near-black):
- Root node = the target, always present.
- One node per confirmed finding, positioned in its kill-chain-stage
column (falls back to a single flat column when no finding has a
stage yet).
- Edges: from the finding's chains_from parent when the harness set one,
else fanned directly from root — never invents a specific relationship
that doesn't exist in the data.
- Per-node icon inferred from title/evidence/cwe/stage (key/shield/
person/host/db/impact), severity-colored border + corner tick.
- Nodes are clickable — opens the same finding detail modal as the
findings table (PoC included).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0129WdYHccPsH27k5GGuwijd
Real front-end bugs found and fixed:
- [hidden] never worked on any element whose class also sets 'display'
(every .btn, .chip, ...): the browser's built-in '[hidden]{display:none}'
rule and an author rule of equal specificity tie, and the later one in the
cascade wins — so 'Next' stayed visible on the Review step alongside
'Start Exploitation', and 'Open report'/'Stop' rendered during 'starting'.
Fixed with a single global '[hidden]{display:none!important}' override.
- Progress bar was functionally correct but easy to miss (thin, 0%-width,
low-contrast track) and gave no feedback while the agent count is still
unknown (recon phase). Added a border for visibility and an indeterminate
sliding-segment state for the 'agents: ?' window.
- A live run watched in the browser was lost on F5 (jumped back to the
wizard) even though the job keeps running server-side. The active job id
now persists in localStorage; on load the app reconnects the SSE stream
(the server replays its full event buffer) instead of losing the view.
New:
- Findings are now clickable — a detail modal shows every Finding field
(CWE/CVSS/OWASP/MITRE/stage/exploitability/confidence/votes/review status/
auth context/account/agent), endpoint+payload, evidence, impact, business
impact, remediation, and chains_from — in both the live run and past-run
detail views.
- PoC surfacing: the finding modal looks up any script the run wrote to
pocs/ that's cited in the finding's evidence (per the harness's own
doctrine — see pipeline.rs change below), fetches and previews it inline,
with a link to open the raw file. Live runs poll for new PoC files every
5s once the run id is known.
- Pinned-leads confirmation: the live run header now states plainly how
many leads were pinned (and their names) or that selection is auto
(recon-driven) — this was previously buried in the scrolling activity log
behind the harness's unconditional 'Loaded 435 agents' library-size line,
which describes the full agent library, not what will actually run.
Harness doctrine (crates/harness/src/pipeline.rs, pocs_line()):
PoC-writing for black-box findings was previously conditioned on 'when an
issue needs a custom multi-step exploit/script' — vague enough that a
straightforward finding (single-request XSS/SQLi/IDOR) often got no PoC
file at all. Now required for every confirmed Medium+ finding, one
standalone .py/.sh script per finding, and explicit about citing the exact
file name in the finding's evidence field (which is what the web UI now
matches on to link a PoC to its finding).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0129WdYHccPsH27k5GGuwijd
Unchecking one agent in an 8-agent category (7/8 left on) rendered the
category header switch fully unchecked — visually indistinguishable from
'category disabled', even though 7 of 8 agents were still on. The
checkbox's checked state only had two positions; a partial selection had
nowhere to render but off.
Fix: set the master switch's .indeterminate property when 0 < selected <
total, with its own CSS state (grey track, thumb parked halfway) instead
of the on/off track+thumb. Clicking a checkbox out of indeterminate
selects everything, per browser default — unchanged behavior, just an
honest visual for the in-between state.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0129WdYHccPsH27k5GGuwijd
Wizard's Asset step now opens with a required 'Engagement name' field
(validated before advancing or launching). The name isn't a harness/CLI
concept, so it's persisted server-side as runId -> name in
.neurosploit/web-engagement-names.json (keyed off the CLI's own run id,
captured from its 'run id : ns-...' log line) so the sidebar, live run
header, and run detail can label a run by name instead of the raw
target/run-id, surviving a server restart.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0129WdYHccPsH27k5GGuwijd
Full frontend rewrite following a deliberate visual direction (dense
security-operations console — borders over shadows, two radii, one accent,
no gradients/glassmorphism) and fixing real bugs found in review:
- EventSource on the exploit stream never called es.close() on 'done',
so the browser silently reconnected and re-streamed the whole job
(duplicate log lines/findings). Fixed.
- Sidebar 'running' step indicator and openRun() matched ANY running run
instead of the one belonging to the current job (by runId). Fixed.
New:
- 5-step engagement wizard (Asset -> Scope & Auth -> Leads -> Model & Run
-> Review) replacing the single flat board — inspired by the
Discovery/Plan/Exploit/Remediate stage model both a.security and
terra.security use publicly.
- Model is now a real dropdown sourced from /api/providers (mirrors
harness::models::providers()), with an API-key vs. subscription toggle
that disables subscription for API-only providers.
- One Auth & Keys menu: target auth header + named roles (IDOR/BOLA/BFLA
multi-identity testing) materialize into an ephemeral creds.yaml passed
via --creds; per-provider API keys live in server memory only (never on
disk) and are merged into every spawned child's env.
- Generative Attack Path Chaining: findings rendered as kill-chain columns
(recon -> initial-access -> ... -> impact) with chains_from resolved to
parent titles, live in the run view and static in run detail.
- Findings are now a proper table (severity/title/endpoint/CWE/agent/
confidence) instead of stacked cards.
- Explicit light/dark theme toggle persisted in localStorage, defaulting
to light (previously light only won when the OS wasn't in dark mode).
- All UI strings in English.
Backend additions: GET /api/providers, GET/POST/DELETE /api/keys,
ephemeral creds.yaml generation for auth/roles, env override merged into
every exploit-job and REPL child spawn.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0129WdYHccPsH27k5GGuwijd
New web/ app (zero npm deps, Node http built-ins only):
- server.js reads agents_md/ to build a categorized lead board (435 agents
auto-classified into Business Logic / Broken Access Control / Injection /
LLM Application / Auth & Session / SSRF / API / Cloud & Infra / etc.),
reads runs/ for history, and spawns the compiled neurosploit CLI binary
for every exploitation job — structured findings/phase/progress are parsed
from its stdout (finding_json:/phase lines), same signal the TUI uses.
- REPL drawer spawns `neurosploit` with no subcommand (real interactive
session, Reader::Plain over the piped stdin) and streams stdin/stdout —
every /command works exactly as in a terminal, nothing reimplemented.
- SSE endpoints for both job and REPL streams; run/finding/report assets
served under /api/runs/:id/asset/*.
- public/{index,app.js,style.css}: lead board with category toggles + custom
leads + Start Exploitation, live run view (progress/findings/log), run
detail view, REPL drawer — screenshot-inspired layout.
- web/API.md: full endpoint reference. web/README.md: quick start.
Bump version 3.6.9 -> 4.0.0 (Cargo.toml, CLI banners, README/TUTORIAL).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0129WdYHccPsH27k5GGuwijd
Add two new model providers, both usable via API key or --subscription
(local CLI login, no key):
- opencode: OpenCode Zen gateway (OPENCODE_API_KEY, opencode.ai/zen/v1).
Subscription mode drives the `opencode` CLI (`opencode run --auto`).
Supports the Playwright MCP (--mcp): our .mcp.json is converted to
OpenCode's own config schema and injected via OPENCODE_CONFIG.
- nous: Nous Research / Hermes models (NOUS_API_KEY,
inference-api.nousresearch.com/v1). Subscription mode drives the
`hermes` CLI (NousResearch/hermes-agent) on the user's Nous Portal
OAuth login (`hermes setup --portal`), via `hermes chat -q`. No
CLI-level MCP hook — falls back to Hermes's own built-in toolsets
(web/terminal/computer-use).
Both wired into cli_binary_for, installed_cli_backends, cli_login_status
(prompt passed as argv, not stdin — neither CLI reads stdin for this).
Bump version 3.6.8 -> 3.6.9 across Cargo.toml, README, TUTORIAL, setup.sh,
install.ps1, and in-binary version strings. README/.env.example updated
with the new provider rows and subscription-login table.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HHFAVCHMvRkTy9Wgw7SayG
- Add RECON_TOTAL_BUDGET_SECS (300s) total wall-clock cap across all rounds
- Per-round budget directive in prompt: 30-50 commands max, stop early if enough intel
- Elapsed time check between rounds: skip remaining if budget exhausted
- Remaining time communicated to follow-up rounds for self-pacing
- RELEASE.md updated with recon budget section
Previously: subscription CLI recon ran 150+ commands over 15 min, exploitation never started.
Now: recon caps at 5 min total, then proceeds to agent exploitation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- models.rs: detect connection-refused and timeout on local providers
(ollama/litellm/llamacpp), show actionable error instead of raw reqwest
- pipeline.rs: findings with empty evidence skip adversarial vote (which
always rejects per 'default to rejected' prompt) and go straight to
needs-review for human triage
- pipeline.rs: warn when single-model panel + vote_n=1 (same model
validates its own findings = weaker validation)
- Bump version 3.6.7 → 3.6.8
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011739wMqPJJPttTLLX6YoQH
Version bump 3.6.5 -> 3.6.6.
Local & uncensored models
- New `llamacpp:` provider (llama-server, OpenAI-compatible, localhost:8080,
no API key, CPU-only or GPU-offloaded). Override via LLAMACPP_BASE_URL;
model name is the loaded gguf (pass-through). 15 -> 16 providers.
- README: local/uncensored highlight, provider table + key-less note, badges.
Quality
- clippy clean under `-D warnings`: clamp(), sort_by_key(Reverse), struct-literal
init, too_many_arguments allows, scoped await_holding_lock on the REPL blocking
fallback (guard intentionally held across run().await), plus clippy --fix set.
CI
- examples/github-actions/ci.yml: cargo build/test/clippy -D warnings for the
neurosploit-rs workspace (template, kept out of .github/workflows).
Claude-Session: https://claude.ai/code/session_01QDses7zTSa9YF7pPRjphvh
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
GitHub automation
- integrations: github_set_status (commit status), github_pr_review
(REQUEST_CHANGES/APPROVE), github_pr_head_sha, and a shared severity
gate (severity_rank / worst_confirmed_rank / gate_trips — confirmed
findings only).
- `neurosploit pr --fail-on <critical|high|medium|low>`: on a confirmed
finding at/above the threshold, sets a failing `neurosploit/security`
commit status, posts a REQUEST_CHANGES review, and exits 2 so a CI
check fails — branch protection then blocks the merge.
- Two ready GitHub Actions: neurosploit-pr-gate.yml (review + block every
PR) and neurosploit-mention.yml (writers comment @neurosploit <text> to
trigger a scan; any language; URL → black-box, else PR review).
Natural-language REPL
- Intent now also parses spoken toggles/knobs across PT/EN/ES: Burp/proxy,
browser/MCP, subscription, "N votos/votes", recon depth (number or
quick/deep/exhaustive), plus stop verbs. handle_nl returns the follow-up
command (/run or /stop).
Docs: README trimmed to features (version changelog stays in RELEASE.md),
new automations documented in README + TUTORIAL-INTEGRATION.
Tests: gate (3), NL toggles/stop (added). All green.
Claude-Session: https://claude.ai/code/session_018BGLy4j5qsqqid6CoovowC
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Type a plain sentence (no slash) and NeuroSploit configures the session
and can launch — no manual flags. Hybrid parser:
- Deterministic fast-path (0 tokens): extracts target/host, model
shorthands (opus/sonnet/gpt/gemini/grok), run verbs and keyworded
clauses (focus / objective / out-of-scope / auth) across PT/EN/ES.
- Model fallback: when the phrase is ambiguous, the configured model
structures it into a JSON intent — works in any language.
Intent maps onto target/repo/models/focus/objective/out_of_scope/auth/
scope; if the request says "run/roda/prueba" it falls through to /run.
Falls back to setting focus when nothing structured is found or offline.
e.g. "testa https://loja.com com opus, foco em SQLi, fora de escopo /admin, roda".
Tests cover PT/EN/ES fast-path, clause parsing, host heuristic, alias
resolution, and the ambiguity gate.
Claude-Session: https://claude.ai/code/session_018BGLy4j5qsqqid6CoovowC
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* feat: embed proof screenshots in reports, correlated to findings
Define a convention that ties each proof image to its vulnerability and
renders it in every report format.
- Finding gains `screenshots: Vec<String>` (paths relative to the run
workdir, e.g. evidence/<finding-id>-1.png).
- Exploit prompt injects an EVIDENCE SCREENSHOTS doctrine: agents save
proof PNGs into the run's absolute evidence/ dir named by a vuln slug,
and list them in the finding JSON `screenshots` array.
- collect_evidence() resolves whatever the agent captured (absolute,
workdir-relative, evidence/, /tmp basename), copies it to a stable
evidence/<finding-id>-N.png, and rewrites the field; unresolved refs
are dropped so a report never embeds a missing image.
- Typst (image()), HTML (<img>) and Markdown (![]) render each finding's
screenshots beside its evidence.
Tests: slugify + collect_evidence resolution/rename; verified a real PDF
compiles with an embedded image.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018BGLy4j5qsqqid6CoovowC
* feat: source-able env.sh to activate neurosploit in the current shell
Add env.sh: `source` it to export NEUROSPLOIT (binary path),
NEUROSPLOIT_BASE (agents base) and prepend the binary dir to PATH —
no reinstall or new terminal needed. Auto-detects the install/repo dir,
honors NEUROSPLOIT_DIR, idempotent. setup.sh now writes a ready env.sh
into the install dir and points users at `source <dir>/env.sh`.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018BGLy4j5qsqqid6CoovowC
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Drop committed exploitation/scan debris from neurosploit-rs/:
proof screenshots (cj_proof2.png, clickjack_proof.png), hackersec
scan dumps (hs_hdr.txt, hs_index.html, hs_robots.txt, hs_sitemap.xml)
and rl_codes.txt. Keep creds.example.yaml (legit sample config).
Add neurosploit-rs/.gitignore so target/, run state, and scan debris
(*.png, hs_*, rl_codes.txt) never get committed again.
Claude-Session: https://claude.ai/code/session_018BGLy4j5qsqqid6CoovowC
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Add two operator inputs that give agents more test context, both
funneled through operator_directives() so they reach every recon/
exploit prompt (web, host, ai, skills):
- objective: WHY the test runs and WHAT counts as impact — rendered
as high-priority ENGAGEMENT OBJECTIVE context.
- out_of_scope: hosts/paths/techniques to exclude — rendered as a
HARD CONSTRAINT the agents must skip and never report against.
REPL: /objective and /scope-out commands (accumulating), optional
onboarding prompts, /show + /help + Tab-complete, session.json
persistence (serde default for back-compat).
CLI: neurosploit run --objective --out-of-scope.
Version unchanged (3.6.5).
Claude-Session: https://claude.ai/code/session_018BGLy4j5qsqqid6CoovowC
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
- Preflight: abort a run early with '✗ target unreachable … is DOWN' when the
probe gets no HTTP response, instead of running agents against a dead host;
print '✓ target is UP' otherwise.
- When no --auth/creds are set on a web run, force account_registration_and_forms
to run first so the authenticated surface is always attempted and visible.
- Move the credential vault to <cwd>/.neurosploit/vault/<run-id>.json (persistent
project store) via new RunConfig.vault_dir; header now prints the vault path at
launch. engagement_ops + finish() resolve paths through vault_paths().
- New agent account_registration_and_forms (+1 → 430): analyzes the app's forms
and self-registers a benign test account (curl or Playwright) to reach the
authenticated surface when no creds are given.
- Probe extracts form details (action/method/fields/kind/CSRF) so form analysis is
grounded; shown in the probe summary and recon JSON.
- Hard anti-flood guardrail in SAFETY_DOCTRINE + the agent: at most 2 accounts per
engagement, never loop/script/batch the register endpoint or flood the DB; reuse
the account made; a test needing many sign-ups is a lead, not mass-creation.
- Credential vault: engagement_ops directive tells agents to append created
accounts to <run-dir>/vault.jsonl; finish() consolidates to vault.json, masks
secrets in the report, and adds a 'Test accounts created (DELETE after)' cleanup
finding listing each account and how it was created.
- Finding tagging: new auth_context (authenticated/unauthenticated) and account
fields, rendered per-finding in the HTML report.
- Opt-in disposable email (off by default): /tempmail on + RunConfig.temp_email;
agents may use the free mail.tm API to read a registration confirmation code.
- Tests: parse_forms unit tests; docs updated (README/TUTORIAL/RELEASE), counts 430.
- Add 12 technique/scenario LLM red-team agents (AI category 18 → 30, total 429):
jailbreaks — AdvPrefix, PAIR, TAP, Crescendo, many-shot, persona/DAN,
encoding/obfuscation, refusal-suppression; prompt-injection scenarios — direct,
indirect (RAG/web/email/tool output), goal hijacking, tool/function-call abuse,
system-prompt/secret exfiltration. Each runs an attacker→LLM-judge loop
(baseline refusal → technique across variants → verdict), proving the bypass
with a benign, redacted receipt. Generated by scripts/build_llm_redteam_v365.py.
- Add REDTEAM_DOCTRINE and inject it into run_ai so every AI test follows the
baseline→technique→judge method across scenarios.
- Models: add Claude Opus 5 and Sonnet 5 (Anthropic) and a new Moonshot AI (Kimi)
provider with Kimi K3/K2 (moonshot:kimi-k3, MOONSHOT_API_KEY) — 15 providers.
- Docs: README/TUTORIAL/RELEASE — new AI/LLM red-team engagement mode + section,
model/env-key tables, agent-library counts (429), badges.
Also includes the v3.6.4 grounding fix (#33) landing on main.
The grounding gate ran in empirical mode for every engagement, demoting
white-box (and skills/n8n audit) findings that had passed the n-model vote
because a file:line code citation isn't raw tool output. Grounding is now
mode-aware:
- Symbolic (white-box SAST / skills): a file:line reference into the reviewed
source, or a quote of code present in it, is the receipt — no live target.
- Empirical (black-box / host / AI): evidence must resemble tool output (as before).
- Either (grey-box): a source citation OR a tool receipt grounds a finding.
The symbolic check runs against the reviewed source corpus (not the transcript)
and falls back to a structural file:line + quote check when the corpus is
unavailable. Adds unit tests incl. a regression test for #33.
- /continue (and /resume) now relaunch a recovered interrupted run on the same
target, carrying its findings forward and steering agents to widen coverage /
chain from them instead of re-reporting. Offer shown at launch; a fresh /run
supersedes it. Findings merge (dedup by title+endpoint) across both runs.
- Opening /results, /finding or /report while a run streams no longer corrupts
the terminal: live background output is paused for the picker (still captured
in /logs) and restored on exit, so Ctrl-C in a picker can't take the process
down mid-run.
A missing or un-downloadable recon tool must never block the run. Both the recon
intensity directive and the general tool doctrine now instruct agents to:
- wrap every install in `timeout 90 <install> || echo skip` and run non-interactively
- try each tool install at most once; on failure/no-package/no-network/hang, skip
immediately and fall back to an installed alternative or curl/nc/dig/python3
- never wait on, retry, or block the whole recon for a single tool download
- Drive `codex exec --json` and parse its JSONL event stream into the same
categorized live feed as Claude Code (exec/edit/tool/net/tokens), so recon and
exploitation are visible as each command runs instead of a silent black box.
- Fix the activity feed to keep per-agent tool events (commands, network, files,
findings) and only filter model reasoning + token telemetry, so /logs shows the
real command trail and /status 'last:' is a true sign-of-life.
- Surface failed internal commands as 'exec: (exit N)'; keep Codex auth/rate
detection from stderr.
- /status now shows progress in EVERY phase: a real bar once agents are selected,
otherwise the current pre-exploit phase + counters (cmds, activity lines), plus
a "last:" sign-of-life line (the latest activity) and the actual full findings.
Before, the bar only appeared after agent selection, so a long recon looked
frozen. Findings count now uses the full list.
- New /logs [n] — dump the recent activity feed (recon/tools/findings) of the
running test; useful with non-streaming CLIs (codex) or after scrolling. Backed
by a capped feed ring buffer + last/lines counters in RunLive.
Symptom: with a non-streaming subscription CLI (codex), a long/intense recon
showed nothing in the feed ("phase starting") and the 5-min idle guardrail killed
the run before any agent ran.
- render_compact now SHOWS recon/probe/ai-recon/skills-audit/loaded/running lines
(were dropped) so a long recon no longer looks frozen.
- Idle guardrail reworked: resets on ANY streamed activity (not only new
findings) and only ARMS after exploitation starts (agent launch / vote) — recon
can never trip it. Message: "no activity in N min".
- RunLive.ingest sets phase=recon on recon/probe lines (was stuck at "starting").
`codex exec` in --dangerously-bypass-approvals-and-sandbox mode exits non-zero
when a tool/command it ran internally (curl/nmap/etc.) returned non-zero — even
though it produced a valid final answer. chat_cli treated any non-zero exit as a
hard failure and dropped the output ("recon round 1 failed ... exit 1"). Now, on
non-zero exit WITH usable stdout and no auth/rate/quota keyword, we use the
output; only genuine auth/rate/quota errors (or empty output) fail hard.
Added the OpenAI GPT-5.6 line to the provider pool: gpt-5.6-sol (frontier/default),
gpt-5.6-terra (balanced), gpt-5.6-luna (fast/affordable). Version 3.6.0 -> 3.6.1.
Recon was a single quick model pass — now it's deep and iterative:
- deep_recon(): an initial deep enumeration pass then follow-up EXPANSION rounds
that chase discovered subdomains/hosts/endpoints/params, converging when a
round finds nothing new. Rounds scale with intensity.
- recon_intensity_directive(): tells the agent HOW hard to recon and to INSTALL
the tools it needs (apt/pip/go/npm/cargo) — subfinder/amass/httpx/gau/katana/
gf/arjun/ffuf/nuclei/nmap/dnsx/linkfinder/whatweb/nikto/testssl — chained
(subfinder->httpx->katana/gau->gf->ffuf); covers subdomains, crawl+wayback, JS,
content/param discovery, ports, versions, API, exposures, TLS/headers.
- RunConfig.recon_intensity (default 3) + REPL /recon <1-4> + CLI --recon <1-4>
(1 quick .. 4 exhaustive); shown in /show.
- DECISION_DOCTRINE injected into exploit/grey/chain prompts: analyse responses to
pick the technique; map & connect routes (endpoint output → next endpoint input);
hunt sensitive flows; mine parameters (incl. hidden from JS/source maps) and test
per-param; mock realistic (non-PII) data to reach deeper logic; exploit the
authenticated surface after login and compare roles; build PoCs when a proof
needs an artifact; bypass 401/403/redirect controls.
- REPL /auth now supports multiple named identities (/auth admin <hdr>, /auth user
<hdr>; bare token → Bearer). With >=2 roles the run gets the access-control
directive (IDOR/BOLA/BFLA/privesc, authorized-vs-unauthorized) and tests both.
- +6 decision agents (library 389): param_miner, endpoint_flow_linker,
authenticated_surface_exploit, clickjacking_poc (HTML PoC), csrf_poc (HTML PoC),
access_control_bypass.
- Docs: counts 383->389, RELEASE + /auth help updated.
- setup.sh: downloads the prebuilt release asset for the detected OS/arch (no Rust
needed; latest release auto-resolved), installs binary + agents_md to
~/.neurosploit-app, symlinks into ~/.local/bin, and PERSISTS PATH +
NEUROSPLOIT_BASE into the shell rc (bash/zsh/fish). Falls back to a source build
(NEUROSPLOIT_BUILD=1 to force). Idempotent.
- install.ps1: same for Windows — downloads windows-x64 zip, installs to
%LOCALAPPDATA%\NeuroSploit, sets User PATH + NEUROSPLOIT_BASE (setx), source-build
fallback (incl. arm64).
- find_base(): auto-discovers agents_md/ NEXT TO THE EXECUTABLE (resolves the PATH
symlink via current_exe) and at common install dirs — so `neurosploit` runs from
ANY folder even without the env var. Env override still takes precedence.
Verified: symlinked binary run from /tmp with no env finds all 383 agents.