feat(3.6.7): CVE exploitation pipeline, PoC-in-report, any-primitive chaining, --only, whitebox doctrine (#41)

Version 3.6.6 -> 3.6.7. +5 agents (430 -> 435).

CVE exploitation pipeline (agents_md/vulns)
- cve_version_fingerprint: pin exact component versions for precise CVE mapping.
- cve_research_analyst: map versions -> NVD/GHSA CVEs, judge reachability/exploitability.
- cve_poc_finder: locate/vet/adapt a public PoC, run non-destructively.
- cve_exploit_scripter: write a custom exploit to $NEUROSPLOIT_POCS when none exists.

Reproducibility
- report::pocs_section lists the run's pocs/ scripts in a "Reproduction — PoC
  scripts" section; write_all appends it to report.md. Whitebox/CVE agents told
  to write repro scripts to $NEUROSPLOIT_POCS and cite the path.

Chaining (any primitive)
- CHAIN_DOCTRINE: reduce any foothold to a primitive and pivot (upload->RCE,
  SSRF->cloud creds, IDOR->takeover, ...), reuse looted creds, reason about
  business logic. New chain_cve_to_rce_to_pivot recipe. Non-destructive guardrails
  (no data loss / DB overwrite / DoS) kept via SAFETY_DOCTRINE.

Re-test one vuln
- --only <agent> on run/whitebox/greybox sets cfg.pinned to run exactly those
  agents, skipping recon selection (implements the previously-unused pinned field).

White-box scoping
- WHITEBOX_DOCTRINE prepended to code agents: static source-only, symbolic
  file:line receipts, source->sink taint, manifest version->CVE; blocks
  hallucinated live/black-box actions.

Verified: cargo build/test (29 passed), clippy -D warnings (exit 0), agents load
(vulns 245, chains 13, total 435), --only flag present.


Claude-Session: https://claude.ai/code/session_01QDses7zTSa9YF7pPRjphvh

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Joas A Santos
2026-08-04 10:44:18 -03:00
committed by GitHub
co-authored by Claude Fable 5
parent 76b56898d1
commit cb19e2194d
14 changed files with 423 additions and 40 deletions
+28 -12
View File
@@ -1,4 +1,4 @@
<h1 align="center">🧠 NeuroSploit v3.6.6</h1>
<h1 align="center">🧠 NeuroSploit v3.6.7</h1>
<p align="center">
<a href="https://trendshift.io/repositories/22624?utm_source=trendshift-badge&amp;utm_medium=badge&amp;utm_campaign=badge-trendshift-22624" target="_blank" rel="noopener noreferrer"><img src="https://trendshift.io/api/badge/trendshift/repositories/22624/daily?language=Python" alt="JoasASantos%2FNeuroSploit | Trendshift" width="250" height="55"/></a>
@@ -12,10 +12,10 @@
</p>
<p align="center">
<img src="https://img.shields.io/badge/Version-3.6.6-blue?style=flat-square">
<img src="https://img.shields.io/badge/Version-3.6.7-blue?style=flat-square">
<img src="https://img.shields.io/badge/Harness-Rust%20%7C%20tokio-e6b673?style=flat-square">
<img src="https://img.shields.io/badge/License-MIT-green?style=flat-square">
<img src="https://img.shields.io/badge/MD%20Agents-430-red?style=flat-square">
<img src="https://img.shields.io/badge/MD%20Agents-435-red?style=flat-square">
<img src="https://img.shields.io/badge/Models-16%20providers-success?style=flat-square">
<img src="https://img.shields.io/badge/Modes-Black%20%7C%20White%20%7C%20Grey%20%7C%20Host%20%7C%20AI-9cf?style=flat-square">
<img src="https://img.shields.io/badge/Auth-API%20key%20%7C%20Subscription-orange?style=flat-square">
@@ -36,7 +36,7 @@ LLMs** — via **API key** or local **subscription** (Claude Code / Codex / Gemi
Grok) — recons the target, **intelligently selects only the agents that match the
discovered surface**, runs them in parallel, **chains** findings into deeper
impact, and **validates every claim by cross-model voting + tool-receipt
grounding** before reporting. It ships **430 markdown agents** and a **Mission
grounding** before reporting. It ships **435 markdown agents** and a **Mission
Control TUI**.
### Engagement modes
@@ -69,9 +69,14 @@ Control TUI**.
flags, CORS reflection, tech fingerprint, linked JS, 404 baseline, high-signal
paths) and feeds those observed facts into recon, so agent selection and
exploitation decisions are grounded in evidence — not the model's guess.
- 🔗 **Attack chaining** 12 multi-stage chain agents (SQLi→RCE→LPE, SSRF→AWS
creds, upload→LFI→RCE→LPE, default-creds→domain, …); each stage proven before
advancing.
- 🔗 **Attack chaining — any primitive pivots.** 13 multi-stage chain agents
(SQLi→RCE→LPE, SSRF→cloud creds, upload→LFI→RCE→LPE, CVE→RCE→pivot, …) **plus a
chaining doctrine** that turns *any* confirmed foothold into the next step:
reduce it to a primitive (exec / read / write / request-forgery / identity /
secret) and pivot — file-upload→RCE, SSRF→metadata creds, IDOR→takeover — reusing
looted creds and reasoning about **business logic** (payment/tenancy/workflow
abuse). Each stage proven; strictly non-destructive (no data loss, no DB
overwrite, no DoS).
- ☁️ **Cloud testing** — AWS / GCP / Azure agents that drive the provider CLIs
(`aws`/`gcloud`/`az`). Connect via `creds.yaml`: AWS keys, a Google
service-account JSON, or an Azure service principal — see
@@ -84,12 +89,23 @@ Control TUI**.
attacker→**LLM-judge** loop (baseline refusal → technique → verdict) and proves
the bypass with a **benign, redacted** receipt. Maps to OWASP LLM Top 10 (2025),
MCP threats & OWASP AI Exchange; Skill/plugin & **n8n** files audited white-box.
- 🧰 **Misconfig & CVE hunting, safely**dedicated agents for absurd
misconfigs (exposed `.git`/`.env`, debug/actuator, default creds, dashboards,
CORS), a **CVE Hunter** (smart, targeted `nuclei`), a **PoC Developer** (writes
reproducible scripts to the run's `pocs/`), and **rate-limit** testing — all
under a strict **data-safety/PII guardrail** (no destructive or state-changing
- 🧰 **Misconfig & CVE hunting → exploitation, safely**a full CVE pipeline:
**version fingerprint** (pin exact versions) → **research analyst** (map to
NVD/GHSA CVEs, judge reachability) → **PoC finder** (locate/vet/adapt a public
PoC) → **exploit scripter** (write a custom exploit when none exists). Every PoC
is written to the run's **`pocs/` folder and referenced in the report** so
findings are reproducible. Plus absurd-misconfig agents (exposed `.git`/`.env`,
debug/actuator, default creds, dashboards, CORS) and rate-limit testing — all
under a strict **data-safety/PII guardrail** (no destructive/state-changing
actions; PII proven with a masked sample, never dumped).
- 🎯 **Re-test one vulnerability**`--only <agent>` (repeatable /
comma-separated) runs exactly the agent(s) you name and skips recon-based
selection — re-test a single finding fast. Works on `run` / `whitebox` /
`greybox`; `neurosploit agents` lists the names.
- 🔬 **White-box stays white-box** — code agents run under a static-review
doctrine (symbolic `file:line` receipts, source-to-sink taint tracing, manifest
version→CVE) that forbids hallucinated live/black-box network actions, and can
emit a repro PoC to `pocs/`.
- 🗣️ **Natural-language REPL** — in the interactive session, just describe what
you want, in any language: *"testa https://loja.com com opus, foco em SQLi,
fora de escopo /admin, roda"*. A hybrid parser sets target/models/focus/
+34
View File
@@ -1,3 +1,37 @@
# NeuroSploit v3.6.7 — Release Notes
**Release Date:** August 2026
**Codename:** Chain & Exploit
**License:** MIT
**Credits:** Joas A Santos & Red Team Leaders
## Highlights
- **CVE exploitation pipeline — 4 new agents.** `cve_version_fingerprint` (pin
exact versions) → `cve_research_analyst` (map to NVD/GHSA, judge reachability) →
`cve_poc_finder` (locate/vet/adapt a public PoC) → `cve_exploit_scripter` (write
a custom exploit when none exists). Focus: actually exploiting vulns that have
CVEs, not just flagging versions.
- **PoCs land in the run's `pocs/` folder and are listed in the report.** Every
agent writes runnable proofs to `$NEUROSPLOIT_POCS`; the report gains a
**"Reproduction — PoC scripts"** section so findings replay end-to-end.
- **Chaining for any primitive.** New `CHAIN_DOCTRINE` + a `chain_cve_to_rce_to_pivot`
recipe turn any confirmed foothold into the next step (upload→RCE, SSRF→cloud
creds, IDOR→takeover, CVE→RCE→pivot), reusing looted creds and reasoning about
**business logic** — strictly non-destructive (no data loss / DB overwrite / DoS).
- **`--only <agent>` — re-test a single vulnerability.** Runs exactly the named
agent(s), skipping recon selection. On `run` / `whitebox` / `greybox`; repeatable
or comma/semicolon-separated. (Implements the previously-dead `pinned` allowlist.)
- **White-box stays white-box.** A `WHITEBOX_DOCTRINE` keeps code agents in static
source-review mode (symbolic `file:line` receipts, source→sink taint, manifest
version→CVE) and blocks hallucinated live/black-box network actions; agents can
emit a repro PoC.
- **435 markdown agents** (was 430).
**Full changelog:** https://github.com/JoasASantos/NeuroSploit/compare/v3.6.6...v3.6.7
---
# NeuroSploit v3.6.6 — Release Notes
**Release Date:** August 2026
@@ -0,0 +1,42 @@
# Known-CVE → RCE → Pivot Chain Agent
## User Prompt
You are executing a multi-stage ATTACK CHAIN against **{target}**: a known CVE in a fingerprinted component → code execution → post-exploitation pivot.
**Recon Context / prior findings:**
{recon_json}
**GOAL:** Turn a version-matched, reachable CVE into demonstrated RCE/access, then pivot — safely.
**CHAIN — advance stage by stage; PROVE every stage with raw tool output before advancing:**
### Stage 1. Pin the target CVE
- From the component+version inventory, pick the highest-impact reachable CVE (unauth RCE/SQLi/SSRF/deserialization first). Confirm preconditions are met
### Stage 2. Obtain a safe PoC
- Reuse a vetted public PoC or write one to `$NEUROSPLOIT_POCS`. STRIP any destructive payload; use a benign marker (`id`, unique echo, OOB callback)
### Stage 3. Execute & confirm
- Run it non-destructively against the authorized target; capture output proving exploitation (marker/OOB/leak)
### Stage 4. Pivot
- From the foothold: loot creds/keys/config/source, reuse them, escalate privileges, reach internal services/cloud metadata, or expand to adjacent hosts — each step proven, none destructive
### 5. Report Format
Report the chain as ONE finding (plus per-stage evidence):
```
FINDING:
- Title: [CVE-id] → RCE → Pivot Chain
- Severity: Critical
- CWE: CWE-1395
- Endpoint: [entry point]
- Vector: [full chain, stage by stage]
- Payload: [PoC path in $NEUROSPLOIT_POCS + key commands per stage]
- Evidence: [raw output proving EACH stage]
- Impact: [demonstrated compromise + what the pivot reached]
- Remediation: Patch to the fixed version; segment/limit blast radius; rotate exposed secrets
- chains_from: [ids of the prerequisite findings this builds on]
```
## System Prompt
You are an exploit-chaining specialist for known CVEs. Only advance a stage after the previous one is proven with a real tool receipt — never assume. Save any PoC to $NEUROSPLOIT_POCS and cite it. If a stage can't be proven, stop and report the chain up to the last proven stage. AUTHORIZED engagement. DATA SAFETY: benign proof only — never destroy/overwrite/encrypt/mass-exfiltrate data, drop databases, or DoS; mask PII; reuse looted creds only against the authorized target. Credits: Joas A Santos & Red Team Leaders.
+39
View File
@@ -0,0 +1,39 @@
# CVE Exploit Scripter Agent
## User Prompt
You are testing **{target}**: when no clean public PoC exists for a confirmed-candidate CVE, WRITE a custom exploitation script and prove it safely.
**Recon Context:**
{recon_json}
**METHODOLOGY:**
### 1. Decide
- Use this when the CVE is reachable but there's no usable public PoC, or the public one is destructive/unsuitable and must be rebuilt safely
### 2. Build from the advisory
- From the CVE/advisory and the component's behaviour, derive the exact request/steps that trigger the bug. Write a runnable script (python/bash/curl) to `$NEUROSPLOIT_POCS` with a header comment: target, CVE id, what it proves, usage
### 3. Make it safe by construction
- Use a BENIGN proof: echo a unique marker, trigger an OOB DNS/HTTP callback, read a non-sensitive indicator, or run `id`/version — never a payload that deletes/overwrites data, drops the DB, or DoSes. Idempotent and minimal
### 4. Run & confirm
- Execute against the authorized target; capture raw output proving exploitation. Keep the script in `$NEUROSPLOIT_POCS` and reference its path so the finding is fully reproducible
### 5. Report Format
For each CONFIRMED finding:
```
FINDING:
- Title: [CVE-id] exploited via custom script on [component]
- Severity: [CVSS/impact]
- CWE: [CVE's CWE]
- Endpoint: [full URL/resource]
- Vector: [technique built from the advisory]
- Payload: [script path in $NEUROSPLOIT_POCS + exact invocation]
- Evidence: [raw output proving exploitation - marker/OOB/leak]
- Impact: [demonstrated impact - up to full compromise]
- Remediation: Upgrade to the fixed version; apply advisory mitigations
```
## System Prompt
You are a custom-exploit developer for known CVEs. AUTHORIZED engagement. Build the exploit from the advisory and PROVE it with a benign, non-destructive marker only. ALWAYS write the script to $NEUROSPLOIT_POCS with a header comment and cite its path — reproducibility is mandatory. Report ONLY what a real tool receipt proves; if you cannot reach a working benign PoC, report the CVE as a reachable exposure, not a confirmed exploit. DATA SAFETY: never destroy/overwrite/encrypt/mass-exfiltrate data or change state beyond the minimal proof; mask PII; no destructive/DoS. Credits: Joas A Santos and Red Team Leaders.
+39
View File
@@ -0,0 +1,39 @@
# CVE PoC Finder Agent
## User Prompt
You are testing **{target}**: find, vet and run a PUBLIC proof-of-concept for a confirmed-candidate CVE, safely.
**Recon Context:**
{recon_json}
**METHODOLOGY:**
### 1. Locate a PoC
- Search `searchsploit`/Exploit-DB, GitHub (CVE id + component), NVD references, `nuclei` templates (`-t` for the CVE/tech tags — targeted, not a blind full scan), packet-storm, vendor advisories
### 2. Vet before you run
- READ the PoC first. Reject/neutralise anything destructive (drops tables, wipes files, ransomware-style, mass requests/DoS, backdoors). Understand exactly what it does and what it proves
### 3. Adapt & stage
- `git clone`/download into the run's `$NEUROSPLOIT_POCS` directory. Parameterise it for THIS target (URL, port, path, auth). Replace any harmful payload with a benign marker (`id`, unique echo string, OOB DNS/HTTP callback)
### 4. Run & confirm
- Execute non-destructively against the authorized target; capture raw output that proves the CVE (marker echoed, OOB hit, expected leak). Keep the exact script in `$NEUROSPLOIT_POCS` so the finding is reproducible
### 5. Report Format
For each CONFIRMED finding:
```
FINDING:
- Title: [CVE-id] exploited via public PoC on [component]
- Severity: [CVSS/impact]
- CWE: [CVE's CWE]
- Endpoint: [full URL/resource]
- Vector: [technique + PoC source]
- Payload: [PoC path in $NEUROSPLOIT_POCS + exact invocation]
- Evidence: [raw output proving exploitation - marker/OOB/leak]
- Impact: [demonstrated impact]
- Remediation: Upgrade to the fixed version; apply advisory mitigations
```
## System Prompt
You are a public-PoC exploitation specialist. AUTHORIZED engagement. ALWAYS read a third-party PoC before running it and STRIP any destructive/DoS/backdoor behaviour — swap harmful payloads for benign markers. Save the adapted PoC to $NEUROSPLOIT_POCS and cite its path so the result is reproducible. Report ONLY what a real tool receipt proves. DATA SAFETY: never modify/delete/overwrite/exfiltrate data or change state beyond the minimal benign proof; mask PII; no destructive/DoS. Credits: Joas A Santos and Red Team Leaders.
+40
View File
@@ -0,0 +1,40 @@
# CVE Research Analyst Agent
## User Prompt
You are testing **{target}**: research known CVEs for the fingerprinted components and decide which are actually exploitable HERE.
**Recon Context:**
{recon_json}
**METHODOLOGY:**
### 1. Map versions → CVEs
- For each component+version, enumerate CVEs (NVD, GitHub Security Advisories/GHSA, vendor advisories, distro trackers, `searchsploit`). Record CVE id, CVSS, affected/fixed versions, vulnerability class
### 2. Assess exploitability HERE
- Filter to CVEs whose preconditions the target actually meets (reachable endpoint/feature, required config/module enabled, auth level you can reach). Prioritise unauth **RCE / SQLi / auth-bypass / SSRF / deserialization**
- Note whether a public PoC/exploit exists (feeds `cve_poc_finder`) or a custom script is needed (feeds `cve_exploit_scripter`)
### 3. Rank
- Order candidates by (impact × exploitability × reachability). Discard theoretical/unreachable CVEs
### 4. Confirm safely
- Where a benign version/behaviour check can confirm the CVE is present (without exploiting), run it and cite the output
### 5. Report Format
For each candidate (Confirmed if a benign check proves presence, else a version-match lead):
```
FINDING:
- Title: [CVE-id] in [component] [version]
- Severity: [map from CVSS/impact]
- CWE: [CVE's CWE, e.g. CWE-1395]
- Endpoint: [reachable resource]
- Vector: [class + preconditions met]
- Payload: [benign confirmation check, if run]
- Evidence: [raw output / advisory + version match]
- Impact: [what the CVE yields — up to full compromise]
- Remediation: Upgrade to [fixed version]; apply advisory mitigations
```
## System Prompt
You are a CVE research analyst. AUTHORIZED engagement. Distinguish "version matches a CVE" (lead) from "CVE is present and reachable here" (confirmed by a benign check) — never inflate a version match into a confirmed exploit. Cite the advisory and the exact affected/fixed version. Hand exploitation to the PoC finder / exploit scripter. DATA SAFETY: read-only research + benign checks only; no state change; mask PII; no destructive/DoS. Credits: Joas A Santos and Red Team Leaders.
@@ -0,0 +1,37 @@
# CVE Version Fingerprint Agent
## User Prompt
You are testing **{target}** to pin the EXACT version of every component so known CVEs can be mapped precisely.
**Recon Context:**
{recon_json}
**METHODOLOGY:**
### 1. Fingerprint every layer
- Server/proxy (`Server`, `Via`, `X-Powered-By`), app framework, CMS + plugins/themes, JS libraries (from `<script>` src, source maps, `/package.json`, bundle comments), API framework, TLS stack
- Pull versions from: response headers, default/readme/changelog files (`/readme.html`, `/CHANGELOG.md`, `/*.txt`), favicon hash, static asset hashes, error pages, `/.well-known`, `robots.txt`, JS build manifests
### 2. Disambiguate
- When only a range is visible, narrow it: compare asset hashes/behaviour between adjacent releases, check feature/endpoint presence, read embedded build ids/commit hashes
### 3. Build the inventory
- Produce a component → EXACT version table; mark confidence (exact vs range). This inventory feeds `cve_research_analyst` / `cve_hunter`
### 4. Report Format
For each identified component (report as a finding only when the version has known CVEs; otherwise fold into the inventory):
```
FINDING:
- Title: Version Fingerprint - [component] [version]
- Severity: Info
- CWE: CWE-200
- Endpoint: [source header/file/asset]
- Vector: [how the version was determined]
- Payload: [exact request/hash used]
- Evidence: [raw header/file snippet proving the version]
- Impact: Enables precise CVE mapping and targeted exploitation
- Remediation: Suppress version banners; keep components patched
```
## System Prompt
You are a software version-fingerprinting specialist. AUTHORIZED engagement. Report ONLY versions you proved from a real receipt (raw header/file/hash) — never guess a version. Prefer EXACT versions; state confidence when only a range is provable. Your inventory is the input to CVE mapping, so accuracy matters more than volume. DATA SAFETY: read-only; no state change; mask any PII. No destructive/DoS actions. Credits: Joas A Santos and Red Team Leaders.
+2 -2
View File
@@ -871,7 +871,7 @@ dependencies = [
[[package]]
name = "neurosploit"
version = "3.6.6"
version = "3.6.7"
dependencies = [
"anyhow",
"clap",
@@ -888,7 +888,7 @@ dependencies = [
[[package]]
name = "neurosploit-harness"
version = "3.6.6"
version = "3.6.7"
dependencies = [
"anyhow",
"futures",
+1 -1
View File
@@ -3,7 +3,7 @@ members = ["crates/harness", "app"]
resolver = "2"
[workspace.package]
version = "3.6.6"
version = "3.6.7"
edition = "2021"
license = "MIT"
repository = "https://github.com/JoasASantos/NeuroSploit"
+36 -7
View File
@@ -1,4 +1,4 @@
//! NeuroSploit v3.6.6 — interactive harness + CLI (`run` / `whitebox` / `agents` / `models`).
//! NeuroSploit v3.6.7 — interactive harness + CLI (`run` / `whitebox` / `agents` / `models`).
mod repl;
mod tui;
@@ -11,8 +11,8 @@ use std::path::{Path, PathBuf};
#[command(
name = "neurosploit",
version,
about = "NeuroSploit v3.6.6 — multi-model autonomous pentest harness",
long_about = "NeuroSploit v3.6.6 — a Rust multi-model harness that drives a pool of LLMs \
about = "NeuroSploit v3.6.7 — multi-model autonomous pentest harness",
long_about = "NeuroSploit v3.6.7 — a Rust multi-model harness that drives a pool of LLMs \
(API key or local subscription: Claude/Codex/Gemini/Grok) to autonomously test a target. \
After recon it INTELLIGENTLY selects only the agents matching the discovered surface, runs \
them in parallel, then validates every finding by cross-model voting before reporting.\n\n\
@@ -77,6 +77,11 @@ enum Cmd {
/// Open a Jira card per finding (needs the jira integration enabled).
#[arg(long)]
jira: bool,
/// Re-test ONLY these agent(s), skipping recon-based selection — repeatable
/// or comma/semicolon-separated (e.g. `--only sqli --only cve_hunter`).
/// Run `neurosploit agents` for the names.
#[arg(long = "only")]
only: Vec<String>,
/// Verbose: log each agent as it launches, recon, and votes.
#[arg(short, long)]
verbose: bool,
@@ -105,6 +110,9 @@ enum Cmd {
/// Open a Jira card per finding (needs the jira integration enabled).
#[arg(long)]
jira: bool,
/// Re-test ONLY these code agent(s) — repeatable or comma/semicolon-separated.
#[arg(long = "only")]
only: Vec<String>,
#[arg(short, long)]
verbose: bool,
},
@@ -139,6 +147,9 @@ enum Cmd {
subscription: bool,
#[arg(long)]
mcp: bool,
/// Re-test ONLY these agent(s) — repeatable or comma/semicolon-separated.
#[arg(long = "only")]
only: Vec<String>,
#[arg(short, long)]
verbose: bool,
},
@@ -379,7 +390,7 @@ async fn main() -> anyhow::Result<()> {
}
}
}
Cmd::Run { url, models, max_agents, vote_n, chain_depth, recon, offline, subscription, mcp, creds, focus, objective, out_of_scope, jira, verbose } => {
Cmd::Run { url, models, max_agents, vote_n, chain_depth, recon, offline, subscription, mcp, creds, focus, objective, out_of_scope, jira, only, verbose } => {
let url = if url.starts_with("http") { url } else { format!("https://{url}") };
let mut cfg = RunConfig::new(&url);
cfg.max_agents = max_agents;
@@ -392,6 +403,7 @@ async fn main() -> anyhow::Result<()> {
cfg.instructions = focus;
cfg.objective = objective;
cfg.out_of_scope = out_of_scope;
cfg.pinned = parse_only(&only);
if !models.is_empty() {
cfg.models = models;
}
@@ -401,7 +413,7 @@ async fn main() -> anyhow::Result<()> {
let ig = harness::integrations::Integrations::load(&repl::proj_dir());
post_integrations(&ig, &url, &out, jira, false, None).await;
}
Cmd::Whitebox { path, models, max_agents, vote_n, chain_depth, recon, offline, subscription, jira, verbose } => {
Cmd::Whitebox { path, models, max_agents, vote_n, chain_depth, recon, offline, subscription, jira, only, verbose } => {
let path = resolve_source(&base, &path)?; // local path OR github URL/owner/repo
let mut cfg = RunConfig::new(&path);
cfg.max_agents = max_agents;
@@ -411,6 +423,7 @@ async fn main() -> anyhow::Result<()> {
cfg.offline = offline;
cfg.subscription = subscription;
cfg.verbose = verbose;
cfg.pinned = parse_only(&only);
if !models.is_empty() {
cfg.models = models;
}
@@ -419,7 +432,7 @@ async fn main() -> anyhow::Result<()> {
let ig = harness::integrations::Integrations::load(&repl::proj_dir());
post_integrations(&ig, &path, &out, jira, false, None).await;
}
Cmd::Greybox { repo, url, models, creds, focus, max_agents, vote_n, chain_depth, recon, offline, subscription, mcp, verbose } => {
Cmd::Greybox { repo, url, models, creds, focus, max_agents, vote_n, chain_depth, recon, offline, subscription, mcp, only, verbose } => {
let repo = resolve_source(&base, &repo)?; // local path OR github URL/owner/repo
let url = if url.starts_with("http") { url } else { format!("https://{url}") };
let mut cfg = RunConfig::new(&url);
@@ -432,6 +445,7 @@ async fn main() -> anyhow::Result<()> {
cfg.subscription = subscription;
cfg.verbose = verbose;
cfg.instructions = focus;
cfg.pinned = parse_only(&only);
if !models.is_empty() {
cfg.models = models;
}
@@ -751,7 +765,7 @@ pub(crate) fn spawn_engagement(base: &Path, mut cfg: RunConfig, mcp: bool, mode:
println!(" │ ua : {ua}");
write_status(&workdir, "running", &format!("\"target\":{:?}", cfg.target));
println!(" ┌─ NeuroSploit v3.6.6 · by Joas A Santos & Red Team Leaders");
println!(" ┌─ NeuroSploit v3.6.7 · by Joas A Santos & Red Team Leaders");
println!(" │ run id : {run_id}");
println!(" │ target : {}", cfg.target);
println!(" │ models : {}", cfg.models.join(", "));
@@ -896,6 +910,21 @@ pub(crate) fn print_findings(out: &RunOutput) {
}
}
/// Parse repeated `--only` values into a clean agent allowlist. Accepts repeats
/// and comma/semicolon-separated lists (`--only sqli,xss` == `--only sqli --only xss`).
fn parse_only(vals: &[String]) -> Vec<String> {
let mut out: Vec<String> = Vec::new();
for v in vals {
for part in v.split([',', ';']) {
let name = part.trim();
if !name.is_empty() && !out.iter().any(|x| x == name) {
out.push(name.to_string());
}
}
}
out
}
fn sanitize(s: &str) -> String {
let s = s.replace("https://", "").replace("http://", "");
let mut o: String = s.chars().map(|c| if c.is_alphanumeric() { c } else { '_' }).collect();
+2 -2
View File
@@ -1,4 +1,4 @@
//! NeuroSploit v3.6.6 — interactive session (Claude-Code / Codex / Cursor-CLI style).
//! NeuroSploit v3.6.7 — interactive session (Claude-Code / Codex / Cursor-CLI style).
//!
//! Launched when `neurosploit` runs with no subcommand. A persistent REPL with
//! real line editing (arrow-key history recall, Ctrl-A/E/K, paste), model
@@ -370,7 +370,7 @@ pub async fn repl(base: &Path) -> anyhow::Result<()> {
let backends = harness::installed_cli_backends();
println!("\x1b[1m");
println!(" ███╗ ██╗███████╗██╗ ██╗██████╗ ██████╗");
println!(" ████╗ ██║██╔════╝██║ ██║██╔══██╗██╔═══██╗ NeuroSploit v3.6.6");
println!(" ████╗ ██║██╔════╝██║ ██║██╔══██╗██╔═══██╗ NeuroSploit v3.6.7");
println!(" ██╔██╗ ██║█████╗ ██║ ██║██████╔╝██║ ██║ interactive harness");
println!(" ██║╚██╗██║██╔══╝ ██║ ██║██╔══██╗██║ ██║ by Joas A Santos");
println!(" ██║ ╚████║███████╗╚██████╔╝██║ ██║╚██████╔╝ & Red Team Leaders");
+1 -1
View File
@@ -1,4 +1,4 @@
//! NeuroSploit v3.6.6 — TUI "Mission Control" mode.
//! NeuroSploit v3.6.7 — TUI "Mission Control" mode.
//!
//! Concurrent panels that update live while the engagement runs in the
//! background, with a composer input that stays active during execution:
+81 -14
View File
@@ -313,6 +313,37 @@ const DECISION_DOCTRINE: &str = "DECIDE WHERE TO ATTACK (analyse, then act):\n\
- Build PoCs when needed: for issues that need an artifact to prove (clickjacking an HTML page that frames the target; CSRF an auto-submitting HTML form; a multi-step or timing exploit a script), WRITE the PoC to the run's PoC dir, run/validate it, and cite the file in the evidence.\n\
- Test control BYPASSES: when something returns 401/403/redirect or is 'blocked', try to bypass it (verb tampering, path/case/encoding normalization, X-Original-URL / X-Rewrite-URL / X-Forwarded-* headers, missing-vs-invalid token, direct object/API access) and confirm the bypass with the two requests.\n\n";
/// CHAIN doctrine: turn ANY foothold into the next step. A primitive→next-step
/// playbook (not an exhaustive script) so the agent always has a concrete pivot
/// to reason about, plus a push to chain toward BUSINESS impact — all under the
/// non-destructive SAFETY_DOCTRINE (prove RCE/access with a benign marker, never
/// harm data or state).
const CHAIN_DOCTRINE: &str = "CHAIN THE FOOTHOLD (pivot to deeper, provable impact — any primitive can chain):\n\
- Think in primitives, not labels: reduce the foothold to what it GIVES you (code exec, file read, file write, request forgery, a trusted identity, a leaked secret, arbitrary object access) and pick the next step from that.\n\
- Pivot playbook (attempt the fitting ones, prove each with a benign receipt):\n\
· File upload / write RCE: upload a webshell/handler to an executable path or poison a config/`.htaccess`/cron/serialized file; prove with a benign marker (`id`, unique echo, OOB DNS), not damage.\n\
· SSRF cloud/host takeover: hit `169.254.169.254` (IMDSv1/v2), GCP/Azure metadata, internal admin/actuator, `file://`/`gopher://`; loot temp creds/tokens and REUSE them.\n\
· SQLi RCE/LPE: stacked queries, `INTO OUTFILE`/`COPY TO`, UDF, `xp_cmdshell`, read secrets/creds; then reuse creds to log in and escalate.\n\
· LFI/path traversal RCE: log/session/wrapper poisoning, `/proc/self/environ`, read source & secrets; combine with an upload for exec.\n\
· XXE SSRF/file read creds; deserialization/SSTI RCE via a gadget/template sink; prove exec with a marker.\n\
· IDOR/BOLA/mass-assignment account/tenant takeover or role escalation (`role=admin`); open-redirect/XSS/CORS token/session theft ATO.\n\
· Exposed `.git`/backup/`.env`/secrets reconstruct source & keys auth to internal APIs, cloud, DB; default/leaked creds domain/service compromise.\n\
- Reuse loot relentlessly: every credential/JWT/cookie/API key/host you obtain is input to the next step carry it forward across modules and try it everywhere it might be accepted.\n\
- Understand the BUSINESS & LOGIC: reason about what the app is FOR (payments, orders, tenancy, KYC, entitlements) and chain toward business impact payment/price/coupon abuse, cross-tenant data access, entitlement/limit bypass, workflow/state-machine skips (skip approval/verification steps), race conditions on balance/stock. These compound: each finding updates your model of the app for the next probe.\n\
- Stop at proof: demonstrate the impact with the SMALLEST safe step and report the CHAIN end-to-end; never destroy, overwrite, encrypt, mass-exfiltrate, or DoS to 'prove' it.\n\n";
/// WHITEBOX doctrine: this is a STATIC source review — keep the agent in the code,
/// not on the wire. Prevents whitebox runs from hallucinating black-box network
/// actions (curl/nuclei/live requests) they cannot perform here, and pushes for
/// a symbolic `file:line` receipt plus a runnable repro PoC where it adds value.
const WHITEBOX_DOCTRINE: &str = "MODE: WHITE-BOX STATIC SOURCE REVIEW. You are reading source code, NOT a live target.\n\
- Source-only: reason strictly about the provided code. Do NOT curl, run nuclei, browse, or claim any live/HTTP/network result there is no running app here. Any \"I sent a request / got a response\" claim is a hallucination and will be rejected.\n\
- Symbolic receipt: EVERY finding's evidence is a `file:line` citation plus the exact vulnerable code quoted verbatim. The code citation IS the proof. No `file:line` + code quote do not report it.\n\
- Trace, don't guess: follow tainted input from its SOURCE (request param, env, deserialization, file) to a dangerous SINK (SQL/exec/eval/template/path/SSRF/deserialize). Report only when source reaches sink without effective sanitization; note the path (`entry sink`).\n\
- Version CVE (static): read dependency manifests (package.json, requirements.txt, go.mod, pom.xml, Gemfile.lock, Cargo.lock) and pin exact versions; map to known CVEs and cite the manifest line. Flag reachable, exploitable ones over merely-outdated ones.\n\
- Repro PoC (optional but valued): when a finding warrants it, WRITE a proof/repro script to $NEUROSPLOIT_POCS e.g. the exact malicious input + the request/CLI call that would trigger the sink, or a unit-style harness exercising the vulnerable function with a header comment (file:line it proves, how to run). Cite the PoC path in the evidence. Mark clearly that it demonstrates the code path (static-derived), not a live hit.\n\
- Calibrate: High/Critical only when the sink is reachable and exploitable from untrusted input; guarded/unreachable code is Low or a lead.\n\n";
/// Methodology directions for a modern JS SPA backed by a REST/GraphQL API
/// (Angular/React/Vue front + Node/Express-style API — the shape of OWASP Juice
/// Shop and many real apps). These are DIRECTIONS on HOW to hunt each vuln class,
@@ -456,20 +487,37 @@ pub async fn run(cfg: RunConfig, lib: &Library, pool: &ModelPool, tx: Sender<Str
// Use the model to pick the agents whose preconditions match the recon —
// the harness reasons about *which* specialists to run, not all of them.
// Exception: when the operator pinned an explicit set (--only), run EXACTLY
// those and skip recon-based selection — used to re-test a single vuln.
let focus = cfg.instructions.clone().unwrap_or_default();
let chosen = select_agents(pool, &recon, &focus, &ranked, &tx).await;
let selected: Vec<Agent> = if !chosen.is_empty() {
let selected: Vec<Agent> = if !cfg.pinned.is_empty() {
let sel: Vec<Agent> =
ranked.iter().filter(|a| chosen.iter().any(|c| c == &a.name)).cloned().collect();
ranked.iter().filter(|a| cfg.pinned.iter().any(|p| p == &a.name)).cloned().collect();
if sel.is_empty() {
heuristic_select(&ranked, &recon, &focus, cap)
let _ = tx.send(format!("--only matched no agent ({}) — falling back to recon selection",
cfg.pinned.join(", "))).await;
let chosen = select_agents(pool, &recon, &focus, &ranked, &tx).await;
ranked.iter().filter(|a| chosen.iter().any(|c| c == &a.name)).take(cap).cloned().collect()
} else {
sel.into_iter().take(cap).collect()
let _ = tx.send(format!("--only: running exactly {} pinned agent(s): {}", sel.len(),
sel.iter().map(|a| a.name.clone()).collect::<Vec<_>>().join(", "))).await;
sel
}
} else {
// LLM selection failed/empty → recon+focus keyword heuristic, not a blind flat list.
let _ = tx.send("selection empty — using recon-keyword heuristic".into()).await;
heuristic_select(&ranked, &recon, &focus, cap)
let chosen = select_agents(pool, &recon, &focus, &ranked, &tx).await;
if !chosen.is_empty() {
let sel: Vec<Agent> =
ranked.iter().filter(|a| chosen.iter().any(|c| c == &a.name)).cloned().collect();
if sel.is_empty() {
heuristic_select(&ranked, &recon, &focus, cap)
} else {
sel.into_iter().take(cap).collect()
}
} else {
// LLM selection failed/empty → recon+focus keyword heuristic, not a blind flat list.
let _ = tx.send("selection empty — using recon-keyword heuristic".into()).await;
heuristic_select(&ranked, &recon, &focus, cap)
}
};
// Dedup: never run the same agent twice in one engagement.
let mut selected: Vec<Agent> = {
@@ -479,7 +527,7 @@ pub async fn run(cfg: RunConfig, lib: &Library, pool: &ModelPool, tx: Sender<Str
// No creds given → always run the registration/form agent FIRST so the run
// reaches the authenticated surface (and the operator sees it happen). It
// self-registers one test account under the anti-flood guardrail.
if cfg.auth.as_deref().unwrap_or("").trim().is_empty() {
if cfg.pinned.is_empty() && cfg.auth.as_deref().unwrap_or("").trim().is_empty() {
if let Some(reg) = lib.vulns.iter().find(|a| a.name == "account_registration_and_forms") {
if !selected.iter().any(|a| a.name == reg.name) {
let _ = tx.send("no creds set — running account_registration_and_forms first to reach the authenticated surface".into()).await;
@@ -597,7 +645,22 @@ pub async fn run_whitebox(cfg: RunConfig, lib: &Library, pool: &ModelPool, tx: S
}
let mut rl = cfg.rl_path.as_ref().map(|p| RlState::load(Path::new(p))).unwrap_or_default();
let mut ranked: Vec<Agent> = if lib.code.is_empty() { lib.vulns.clone() } else { lib.code.clone() };
let pool_agents: Vec<Agent> = if lib.code.is_empty() { lib.vulns.clone() } else { lib.code.clone() };
let mut ranked: Vec<Agent> = if cfg.pinned.is_empty() {
pool_agents
} else {
// Operator pinned an explicit agent set (--only): re-test exactly those.
let sel: Vec<Agent> = pool_agents.iter()
.filter(|a| cfg.pinned.iter().any(|p| p == &a.name)).cloned().collect();
if sel.is_empty() {
let _ = tx.send(format!("--only matched no code agent ({}) — reviewing with the full set",
cfg.pinned.join(", "))).await;
pool_agents
} else {
let _ = tx.send(format!("--only: reviewing with exactly {} pinned agent(s)", sel.len())).await;
sel
}
};
ranked.sort_by(|a, b| rl.weight(&b.name).partial_cmp(&rl.weight(&a.name)).unwrap_or(std::cmp::Ordering::Equal));
let cap = if cfg.max_agents > 0 { cfg.max_agents.min(ranked.len()) } else { ranked.len() };
let selected: Vec<Agent> = ranked.into_iter().take(cap).collect();
@@ -616,11 +679,15 @@ pub async fn run_whitebox(cfg: RunConfig, lib: &Library, pool: &ModelPool, tx: S
let user = format!(
"{}\n\nSOURCE CODE TO REVIEW:\n```\n{}\n```\n\nReply ONLY with a JSON array of findings (may be empty []). \
Each item: {{id,title,severity,cwe,endpoint,payload,evidence,impact,remediation,confidence}} \
where `endpoint` is the file:line and `evidence` quotes the vulnerable code.",
where `endpoint` is the file:line and `evidence` quotes the vulnerable code. \
When a finding warrants a runnable proof, write a repro script to $NEUROSPLOIT_POCS and put its path in `payload`.",
ag.user.replace("{target}", "the provided repository").replace("{recon_json}", "{}"),
ctx
);
match pool.complete_routed(Task::Exploit, &ag.name, &ag.system, &user).await {
// Prepend the white-box doctrine so code agents stay in static
// source-review mode and never hallucinate live/black-box actions.
let sys = format!("{}{}", WHITEBOX_DOCTRINE, ag.system);
match pool.complete_routed(Task::Exploit, &ag.name, &sys, &user).await {
Ok((m, text)) => {
let f = extract_findings(&text, &ag.name);
let _ = txc.send(format!("analyze {} via {}{} candidate(s)", ag.name, m.label(), f.len())).await;
@@ -910,13 +977,13 @@ async fn chain_from_seed(pool: &ModelPool, target: &str, directives: &str, recon
};
let short: String = seed.title.chars().take(28).collect();
let user = format!(
"AUTHORIZED engagement on {target}.\n\n{directives}{react}{depth}{decision}{safety}{doctrine}\
"AUTHORIZED engagement on {target}.\n\n{directives}{react}{depth}{decision}{chain}{safety}{doctrine}\
FOOTHOLD TO EXPAND (round {round}/{max}):\n- [{}] {} @ {} ({})\n payload: {}\n evidence: {}\n\n\
LOOT GATHERED (reuse it):\n{loot_block}\n\n{recipe_block}RECON:\n{recon_ctx}\n\n\
From THIS foothold, DECIDE the best directions and PROVE new impact post-exploitation (loot creds/keys/config/source), credential reuse, privilege escalation (horizontal & vertical), lateral movement to adjacent services/hosts, data exfiltration, and NEW attack surface it exposes. Every claim needs a real tool receipt.\n\n\
Reply ONLY JSON: {{\"findings\":[{{id,title,severity,cwe,endpoint,payload,evidence,impact,remediation,confidence}}],\"loot\":[\"cred:user:pass@host\",\"token:...\",\"host:10.0.0.5\",\"endpoint:/internal/api\"]}} (empty arrays are fine).",
seed.severity, seed.title, seed.endpoint, seed.cwe, seed.payload, seed.evidence,
react = REACT_DOCTRINE, depth = DEPTH_DOCTRINE, decision = DECISION_DOCTRINE, safety = SAFETY_DOCTRINE, doctrine = tool_doctrine(pool.mcp_config.is_some()),
react = REACT_DOCTRINE, depth = DEPTH_DOCTRINE, decision = DECISION_DOCTRINE, chain = CHAIN_DOCTRINE, safety = SAFETY_DOCTRINE, doctrine = tool_doctrine(pool.mcp_config.is_some()),
);
let label = format!("chain:{short}");
match pool.complete_routed(Task::Exploit, &label, CHAIN_SYS, &user).await {
+41 -1
View File
@@ -413,11 +413,51 @@ pub fn json_report(target: &str, findings: &[Finding], run_id: &str, meta: &Enga
/// Write the full report bundle: Markdown, JSON, HTML, and the Typst/PDF.
/// Returns the primary artifact path (PDF if typst present, else the .typ).
/// A "## Reproduction — PoC scripts" section listing the runnable proof-of-concept
/// scripts agents wrote to `<run>/pocs/`. Each is a self-contained artifact the
/// operator can re-run to replicate a finding, so the report ships with a live
/// reproduction kit — not just prose. Empty string when no PoCs were produced.
pub fn pocs_section(dir: &Path) -> String {
let pocs = dir.join("pocs");
let mut entries: Vec<(String, String)> = Vec::new();
if let Ok(rd) = std::fs::read_dir(&pocs) {
for e in rd.flatten() {
let p = e.path();
if !p.is_file() { continue; }
let name = match p.file_name().and_then(|s| s.to_str()) { Some(n) => n.to_string(), None => continue };
// First non-empty comment line doubles as a one-line description.
let desc = std::fs::read_to_string(&p).ok()
.and_then(|t| t.lines()
.map(|l| l.trim())
.find(|l| l.starts_with('#') || l.starts_with("//") || l.starts_with("/*"))
.map(|l| l.trim_start_matches(['#', '/', '*', ' ']).trim().to_string()))
.unwrap_or_default();
entries.push((name, desc));
}
}
if entries.is_empty() { return String::new(); }
entries.sort();
let mut s = String::from("## Reproduction — PoC scripts\n\n");
s.push_str("Runnable proofs written to `pocs/` during the engagement. Re-run any of \
them to replicate the corresponding finding.\n\n");
for (name, desc) in entries {
if desc.is_empty() {
s.push_str(&format!("- `pocs/{name}`\n"));
} else {
s.push_str(&format!("- `pocs/{name}` — {desc}\n"));
}
}
s.push('\n');
s
}
pub fn write_all(target: &str, findings: &[Finding], dir: &Path) -> std::io::Result<PathBuf> {
std::fs::create_dir_all(dir)?;
let run_id = dir.file_name().and_then(|s| s.to_str()).unwrap_or("run").to_string();
let meta = read_meta(dir);
std::fs::write(dir.join("report.md"), markdown(target, findings, &meta))?;
let mut md = markdown(target, findings, &meta);
md.push_str(&pocs_section(dir));
std::fs::write(dir.join("report.md"), md)?;
std::fs::write(dir.join("report.json"), json_report(target, findings, &run_id, &meta))?;
std::fs::write(dir.join("report.html"), html(target, findings, &meta))?;
typst_report(target, findings, dir)