mirror of
https://github.com/CyberSecurityUP/NeuroSploit.git
synced 2026-07-07 03:47:56 +02:00
v3.5.5 — cloud infrastructure testing + REPL polish
Cloud testing: - +17 cloud agents (agents_md/infra/) for AWS/GCP/Azure: IAM/RBAC privesc, storage exposure (S3/GCS/Blob), compute & network exposure + IMDS, secrets (Secrets Manager / Secret Manager / Key Vault), SA/SP key abuse, Entra ID enum, and a multi-cloud footprint/identity recon agent. Library 348 -> 365. - creds.yaml gains aws:/gcp:/azure: blocks (Creds::cloud). The harness exports provider env vars (AWS_*, GOOGLE_APPLICATION_CREDENTIALS, AZURE_* SP) so aws/gcloud/az authenticate automatically, and injects a cloud directive. GCP inline JSON is written to a temp file. Best-practice auth per provider. REPL polish: - /chain <n> (attack-chain depth, wired to Session.chain_depth), /agents list (library category counts incl. infra/cloud); /show now shows chain-depth and enabled integrations. Tab-completion + help updated. Docs: README badges (365 agents / 14 providers), new "Cloud credentials" section; RELEASE notes. Version 3.5.4 -> 3.5.5.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
//! NeuroSploit v3.5.4 — interactive harness + CLI (`run` / `whitebox` / `agents` / `models`).
|
||||
//! NeuroSploit v3.5.5 — 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.5.4 — multi-model autonomous pentest harness",
|
||||
long_about = "NeuroSploit v3.5.4 — a Rust multi-model harness that drives a pool of LLMs \
|
||||
about = "NeuroSploit v3.5.5 — multi-model autonomous pentest harness",
|
||||
long_about = "NeuroSploit v3.5.5 — 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\
|
||||
@@ -474,6 +474,24 @@ pub(crate) async fn apply_creds(cfg: &mut RunConfig, path: Option<&str>) {
|
||||
cfg.instructions = Some(format!("{hi}\n{base}"));
|
||||
println!(" [*] host credentials loaded (SSH/Windows-AD)");
|
||||
}
|
||||
// Cloud credentials (AWS / GCP / Azure) → export env for the provider CLIs
|
||||
// and tell the agents how to authenticate & what to enumerate.
|
||||
let cloud_env = c.cloud_env();
|
||||
if !cloud_env.is_empty() {
|
||||
for (k, v) in &cloud_env {
|
||||
std::env::set_var(k, v);
|
||||
}
|
||||
let names: Vec<&str> = [
|
||||
(!c.cloud.as_ref().map(|x| x.aws_access_key_id.is_empty() && x.aws_profile.is_empty()).unwrap_or(true), "AWS"),
|
||||
(!c.cloud.as_ref().map(|x| x.gcp_sa_json.is_empty()).unwrap_or(true), "GCP"),
|
||||
(!c.cloud.as_ref().map(|x| x.azure_client_id.is_empty()).unwrap_or(true), "Azure"),
|
||||
].iter().filter(|(on, _)| *on).map(|(_, n)| *n).collect();
|
||||
println!(" [*] cloud credentials loaded ({}) — {} env var(s) exported", names.join("/"), cloud_env.len());
|
||||
if let Some(ci) = c.cloud_instruction() {
|
||||
let base = cfg.instructions.clone().unwrap_or_default();
|
||||
cfg.instructions = Some(format!("{ci}\n{base}"));
|
||||
}
|
||||
}
|
||||
// No direct material but a login flow → perform it now.
|
||||
if cfg.auth.is_none() {
|
||||
if let Some(login) = &c.login {
|
||||
@@ -534,7 +552,7 @@ pub(crate) fn spawn_engagement(base: &Path, mut cfg: RunConfig, mcp: bool, mode:
|
||||
cfg.rl_path = Some(base.join("data").join("rl_state_rs.json").display().to_string());
|
||||
write_status(&workdir, "running", &format!("\"target\":{:?}", cfg.target));
|
||||
|
||||
println!(" ┌─ NeuroSploit v3.5.4 · by Joas A Santos & Red Team Leaders");
|
||||
println!(" ┌─ NeuroSploit v3.5.5 · by Joas A Santos & Red Team Leaders");
|
||||
println!(" │ run id : {run_id}");
|
||||
println!(" │ target : {}", cfg.target);
|
||||
println!(" │ models : {}", cfg.models.join(", "));
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//! NeuroSploit v3.5.4 — interactive session (Claude-Code / Codex / Cursor-CLI style).
|
||||
//! NeuroSploit v3.5.5 — 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
|
||||
@@ -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", "/agents", "/theme", "/clear", "/run", "/stop", "/continue", "/runs", "/results", "/report",
|
||||
"/votes", "/chain", "/agents", "/theme", "/clear", "/run", "/stop", "/continue", "/runs", "/results", "/report",
|
||||
"/status", "/diff", "/retest", "/integrations", "/quit",
|
||||
];
|
||||
|
||||
@@ -198,6 +198,7 @@ struct Session {
|
||||
mcp: bool,
|
||||
vote_n: usize,
|
||||
max_agents: usize,
|
||||
chain_depth: usize,
|
||||
offline: bool,
|
||||
target: Option<String>,
|
||||
repo: Option<String>,
|
||||
@@ -216,6 +217,7 @@ impl Default for Session {
|
||||
mcp: false,
|
||||
vote_n: 3,
|
||||
max_agents: 0,
|
||||
chain_depth: 2,
|
||||
offline: false,
|
||||
target: None,
|
||||
repo: None,
|
||||
@@ -299,7 +301,7 @@ pub async fn repl(base: &Path) -> anyhow::Result<()> {
|
||||
let backends = harness::installed_cli_backends();
|
||||
println!("\x1b[1m");
|
||||
println!(" ███╗ ██╗███████╗██╗ ██╗██████╗ ██████╗");
|
||||
println!(" ████╗ ██║██╔════╝██║ ██║██╔══██╗██╔═══██╗ NeuroSploit v3.5.4");
|
||||
println!(" ████╗ ██║██╔════╝██║ ██║██╔══██╗██╔═══██╗ NeuroSploit v3.5.5");
|
||||
println!(" ██╔██╗ ██║█████╗ ██║ ██║██████╔╝██║ ██║ interactive harness");
|
||||
println!(" ██║╚██╗██║██╔══╝ ██║ ██║██╔══██╗██║ ██║ by Joas A Santos");
|
||||
println!(" ██║ ╚████║███████╗╚██████╔╝██║ ██║╚██████╔╝ & Red Team Leaders");
|
||||
@@ -432,7 +434,22 @@ pub async fn repl(base: &Path) -> anyhow::Result<()> {
|
||||
"/offline" => { s.offline = !matches!(arg, "off" | "false" | "0" | "no"); println!(" offline: {}", onoff(s.offline)); }
|
||||
"/integrations" | "/integration" => integrations_cmd(arg),
|
||||
"/votes" => { s.vote_n = arg.parse().unwrap_or(s.vote_n); println!(" votes: {}", s.vote_n); }
|
||||
"/agents" => { s.max_agents = arg.parse().unwrap_or(s.max_agents); println!(" max agents: {}", s.max_agents); }
|
||||
"/chain" => {
|
||||
if arg.is_empty() { println!(" attack-chain depth: {} (0 disables) — set with /chain <n>", s.chain_depth); }
|
||||
else { s.chain_depth = arg.parse().unwrap_or(s.chain_depth); println!(" attack-chain depth: {}", s.chain_depth); }
|
||||
}
|
||||
"/agents" => {
|
||||
if arg == "list" || arg == "ls" {
|
||||
let lib = agents::load(base);
|
||||
println!(" agent library ({} total):", lib.total());
|
||||
println!(" vulns {} · code {} · infra/cloud {} · recon {} · chains {} · meta {}",
|
||||
lib.vulns.len(), lib.code.len(), lib.infra.len(), lib.recon.len(), lib.chains.len(), lib.meta.len());
|
||||
} else if arg.is_empty() {
|
||||
println!(" max agents: {} (0 = all) — set with /agents <n>, or /agents list for counts", s.max_agents);
|
||||
} else {
|
||||
s.max_agents = arg.parse().unwrap_or(s.max_agents); println!(" max agents: {}", s.max_agents);
|
||||
}
|
||||
}
|
||||
"/clear" => { print!("\x1b[2J\x1b[H"); }
|
||||
"/run" | "/go" => {
|
||||
if active.as_ref().map(|a| !a.done.load(Ordering::Relaxed)).unwrap_or(false) {
|
||||
@@ -667,6 +684,7 @@ async fn run(base: &Path, s: &Session, history: &mut Vec<RunRecord>) {
|
||||
cfg.models = s.models.clone();
|
||||
cfg.subscription = s.subscription;
|
||||
cfg.vote_n = s.vote_n;
|
||||
cfg.chain_depth = s.chain_depth;
|
||||
cfg.max_agents = s.max_agents;
|
||||
cfg.verbose = true;
|
||||
cfg.offline = s.offline;
|
||||
@@ -716,6 +734,7 @@ async fn start_background(base: &Path, s: &Session, reader: &mut Reader,
|
||||
cfg.models = s.models.clone();
|
||||
cfg.subscription = s.subscription;
|
||||
cfg.vote_n = s.vote_n;
|
||||
cfg.chain_depth = s.chain_depth;
|
||||
cfg.max_agents = s.max_agents;
|
||||
cfg.verbose = true;
|
||||
cfg.offline = s.offline;
|
||||
@@ -1062,7 +1081,14 @@ fn show(s: &Session) {
|
||||
println!(" │ auth : {}", s.auth.clone().unwrap_or_else(|| "(none)".into()));
|
||||
println!(" │ creds : {}", s.creds.clone().unwrap_or_else(|| "(none)".into()));
|
||||
println!(" │ focus : {}", s.instructions.clone().unwrap_or_else(|| "(none — tests everything)".into()));
|
||||
println!(" │ opts : mcp={} offline={} votes={} max-agents={}", onoff(s.mcp), onoff(s.offline), s.vote_n, s.max_agents);
|
||||
println!(" │ opts : mcp={} offline={} votes={} chain-depth={} max-agents={}", onoff(s.mcp), onoff(s.offline), s.vote_n, s.chain_depth, s.max_agents);
|
||||
// Integrations at a glance (see /integrations for detail).
|
||||
{
|
||||
let ig = harness::integrations::Integrations::load(&proj_dir());
|
||||
let on: Vec<&str> = [(ig.github.enabled, "github"), (ig.gitlab.enabled, "gitlab"), (ig.jira.enabled, "jira")]
|
||||
.iter().filter(|(e, _)| *e).map(|(_, n)| *n).collect();
|
||||
println!(" │ integr. : {}", if on.is_empty() { "(none — /integrations)".into() } else { on.join(", ") });
|
||||
}
|
||||
// API-key status for the providers your selected models need.
|
||||
if !s.subscription {
|
||||
let provs: std::collections::BTreeSet<String> = s.models.iter()
|
||||
@@ -1111,8 +1137,9 @@ fn help() {
|
||||
|
||||
println!("\n \x1b[2mOPTIONS\x1b[0m");
|
||||
h("/mcp on|off", "Playwright MCP browser /offline on|off self-test");
|
||||
h("/votes <n>", "validator votes /agents <n> cap agents");
|
||||
h("/theme color|mono", "/show (config) /clear /quit");
|
||||
h("/votes <n>", "validator votes /chain <n> attack-chain depth");
|
||||
h("/agents <n>|list", "cap agents · list counts /theme color|mono");
|
||||
h("/show (config)", "/clear /quit");
|
||||
|
||||
println!("\n \x1b[2mMODES — black-box: set /target · white-box: set /repo · grey-box: set BOTH /repo + /target · host: /target <ip> + /creds\x1b[0m");
|
||||
println!(" \x1b[2mFindings are checkpointed live to .neurosploit/ — quit/crash mid-run and they're recovered into /runs next launch.\x1b[0m");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//! NeuroSploit v3.5.4 — TUI "Mission Control" mode.
|
||||
//! NeuroSploit v3.5.5 — 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:
|
||||
|
||||
Reference in New Issue
Block a user