misconfig/CVE/PoC/rate-limit agents, data-safety guardrail, Burp proxy, PoC dir

Agents (+10 → library 375): absurd-misconfig hunters (exposed .git/.env/backups,
debug/actuator, default creds, dir listing, ops dashboards, permissive CORS,
verbose errors), a CVE Hunter (fingerprint → correlate → safe PoC), a PoC
Developer (writes runnable scripts to the run's pocs/), and a Rate-Limit tester.

Doctrine (pipeline):
- SAFETY_DOCTRINE injected into every exploit/chain/host prompt: no modify/delete/
  exfiltrate/state-change without permission; on PII prove with a masked sample +
  count, never dump.
- tool_doctrine adds: smart targeted nuclei (fingerprint-first, -tags/-id, rate/
  timeouts), misconfig hunting, rate-limit control checks, authorized tool
  download (git clone PoC repos / fetch scanners), Burp/ZAP proxy routing, and a
  per-run PoC workspace.

Harness/CLI/REPL:
- RunConfig.proxy; spawn_engagement creates <workdir>/pocs and exports
  NEUROSPLOIT_POCS + NEUROSPLOIT_PROXY (proxy from cfg or the env var).
- REPL /proxy <url> and /burp (Session.proxy); /show shows proxy.

Docs: README highlights + Cloud/counts (375), RELEASE v3.5.5 sections.
This commit is contained in:
CyberSecurityUP
2026-07-01 23:40:47 -03:00
parent 58aa8698cd
commit 5f1573ac7f
18 changed files with 642 additions and 22 deletions
+13
View File
@@ -550,6 +550,19 @@ pub(crate) fn spawn_engagement(base: &Path, mut cfg: RunConfig, mcp: bool, mode:
std::fs::create_dir_all(&workdir).ok();
cfg.workdir = Some(workdir.display().to_string());
cfg.rl_path = Some(base.join("data").join("rl_state_rs.json").display().to_string());
// PoC scratch dir: agents write custom exploit scripts here (see doctrine).
let pocs = workdir.join("pocs");
std::fs::create_dir_all(&pocs).ok();
std::env::set_var("NEUROSPLOIT_POCS", pocs.display().to_string());
// Local intercepting proxy (Burp/ZAP): agents route HTTP through it. Comes
// from cfg.proxy (REPL /proxy) or the NEUROSPLOIT_PROXY env var (CLI).
let proxy = cfg.proxy.clone()
.or_else(|| std::env::var("NEUROSPLOIT_PROXY").ok())
.filter(|p| !p.trim().is_empty());
if let Some(p) = proxy {
std::env::set_var("NEUROSPLOIT_PROXY", &p);
println!(" │ proxy : {p} (traffic routed to Burp/ZAP for inspection)");
}
write_status(&workdir, "running", &format!("\"target\":{:?}", cfg.target));
println!(" ┌─ NeuroSploit v3.5.5 · by Joas A Santos & Red Team Leaders");
+17 -1
View File
@@ -119,7 +119,7 @@ struct LiveCheckpoint {
const COMMANDS: &[&str] = &[
"/help", "/show", "/config", "/providers", "/model", "/key", "/sub", "/target",
"/repo", "/auth", "/creds", "/focus", "/attach", "/context", "/mcp", "/offline",
"/votes", "/chain", "/timeout", "/agents", "/theme", "/clear", "/run", "/stop", "/continue", "/runs", "/results", "/report",
"/votes", "/chain", "/timeout", "/proxy", "/burp", "/agents", "/theme", "/clear", "/run", "/stop", "/continue", "/runs", "/results", "/report",
"/status", "/diff", "/retest", "/integrations", "/quit",
];
@@ -217,6 +217,8 @@ struct Session {
/// Idle guardrail: stop a run if no NEW finding lands in this many seconds
/// (0 = disabled). Set in minutes via `/timeout <mins>`.
idle_secs: u64,
/// Local intercepting proxy (Burp/ZAP), e.g. http://127.0.0.1:8080.
proxy: Option<String>,
offline: bool,
target: Option<String>,
repo: Option<String>,
@@ -237,6 +239,7 @@ impl Default for Session {
max_agents: 0,
chain_depth: 2,
idle_secs: 300, // 5-minute idle guardrail by default
proxy: None,
offline: false,
target: None,
repo: None,
@@ -438,6 +441,15 @@ pub async fn repl(base: &Path) -> anyhow::Result<()> {
else { println!(" idle guardrail: stop if no new finding in {mins} min"); }
}
}
"/proxy" | "/burp" => {
match arg {
"" => println!(" proxy: {}", s.proxy.clone().unwrap_or_else(|| "(none) — route traffic to Burp/ZAP with /proxy <url>, e.g. /proxy http://127.0.0.1:8080".into())),
"off" | "clear" | "none" => { s.proxy = None; println!(" proxy cleared — traffic goes direct"); }
"on" => { s.proxy = Some("http://127.0.0.1:8080".into()); println!(" proxy: http://127.0.0.1:8080 (default Burp) — agents route curl through it"); }
u => { let p = if u.starts_with("http") { u.to_string() } else { format!("http://{u}") };
s.proxy = Some(p.clone()); println!(" proxy: {p} — agents route HTTP through it so you can inspect/replay in Burp"); }
}
}
"/repo" => {
if arg.is_empty() { println!(" repo: {}", s.repo.clone().unwrap_or_else(|| "(none) — set with /repo <path | github-url | owner/repo>, clear with /repo clear".into())); }
else if arg == "clear" { s.repo = None; println!(" repo cleared"); }
@@ -742,6 +754,7 @@ async fn run(base: &Path, s: &Session, history: &mut Vec<RunRecord>) {
cfg.subscription = s.subscription;
cfg.vote_n = s.vote_n;
cfg.chain_depth = s.chain_depth;
cfg.proxy = s.proxy.clone();
cfg.max_agents = s.max_agents;
cfg.verbose = true;
cfg.offline = s.offline;
@@ -795,6 +808,7 @@ async fn start_background(base: &Path, s: &Session, reader: &mut Reader,
cfg.subscription = s.subscription;
cfg.vote_n = s.vote_n;
cfg.chain_depth = s.chain_depth;
cfg.proxy = s.proxy.clone();
cfg.max_agents = s.max_agents;
cfg.verbose = true;
cfg.offline = s.offline;
@@ -1228,6 +1242,7 @@ fn show(s: &Session) {
println!(" │ repo : {}", s.repo.clone().unwrap_or_else(|| "(none)".into()));
println!(" │ auth : {}", s.auth.clone().unwrap_or_else(|| "(none)".into()));
println!(" │ creds : {}", s.creds.clone().unwrap_or_else(|| "(none)".into()));
println!(" │ proxy : {}", s.proxy.clone().unwrap_or_else(|| "(none — /proxy for Burp/ZAP)".into()));
println!(" │ focus : {}", s.instructions.clone().unwrap_or_else(|| "(none — tests everything)".into()));
println!(" │ opts : mcp={} offline={} votes={} chain-depth={} max-agents={} idle-stop={}",
onoff(s.mcp), onoff(s.offline), s.vote_n, s.chain_depth, s.max_agents,
@@ -1289,6 +1304,7 @@ fn help() {
h("/mcp on|off", "Playwright MCP browser /offline on|off self-test");
h("/votes <n>", "validator votes /chain <n> attack-chain depth");
h("/timeout <min>", "idle guardrail: stop if no new finding in <min> (0 = off)");
h("/proxy <url>|off", "route agent HTTP through Burp/ZAP (/burp = default :8080)");
h("/agents <n>|list", "cap agents · list counts /theme color|mono");
h("/show (config)", "/clear /quit");