mirror of
https://github.com/CyberSecurityUP/NeuroSploit.git
synced 2026-08-15 06:00:28 +02:00
feat(3.6.6): local/uncensored llama.cpp provider, clippy clean, CI (#40)
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>
This commit is contained in:
co-authored by
Claude Fable 5
parent
3786d7c559
commit
f913af211d
@@ -1,4 +1,4 @@
|
||||
//! NeuroSploit v3.6.5 — interactive harness + CLI (`run` / `whitebox` / `agents` / `models`).
|
||||
//! NeuroSploit v3.6.6 — 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.5 — multi-model autonomous pentest harness",
|
||||
long_about = "NeuroSploit v3.6.5 — a Rust multi-model harness that drives a pool of LLMs \
|
||||
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 \
|
||||
(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\
|
||||
@@ -542,7 +542,7 @@ async fn main() -> anyhow::Result<()> {
|
||||
std::fs::remove_dir_all(&dest).ok();
|
||||
let url = ig.authed_clone_url(&format!("https://github.com/{owner_repo}"));
|
||||
if run_git(&["clone", "--depth", "1", "--branch", &branch, &url, &dest.display().to_string()]).is_ok() {
|
||||
let mut cfg = RunConfig::new(&dest.display().to_string());
|
||||
let mut cfg = RunConfig::new(dest.display().to_string());
|
||||
cfg.subscription = subscription;
|
||||
cfg.verbose = verbose;
|
||||
if !models.is_empty() { cfg.models = models.clone(); }
|
||||
@@ -751,7 +751,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.5 · by Joas A Santos & Red Team Leaders");
|
||||
println!(" ┌─ NeuroSploit v3.6.6 · 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.6.5 — interactive session (Claude-Code / Codex / Cursor-CLI style).
|
||||
//! NeuroSploit v3.6.6 — 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
|
||||
@@ -361,12 +361,16 @@ impl Reader {
|
||||
}
|
||||
}
|
||||
|
||||
// The blocking (piped, no external printer) fallback holds the history
|
||||
// MutexGuard across `run().await` on purpose — run() mutates that history for
|
||||
// the whole async operation and no other task contends for it there.
|
||||
#[allow(clippy::await_holding_lock)]
|
||||
pub async fn repl(base: &Path) -> anyhow::Result<()> {
|
||||
let lib = agents::load(base);
|
||||
let backends = harness::installed_cli_backends();
|
||||
println!("\x1b[1m");
|
||||
println!(" ███╗ ██╗███████╗██╗ ██╗██████╗ ██████╗");
|
||||
println!(" ████╗ ██║██╔════╝██║ ██║██╔══██╗██╔═══██╗ NeuroSploit v3.6.5");
|
||||
println!(" ████╗ ██║██╔════╝██║ ██║██╔══██╗██╔═══██╗ NeuroSploit v3.6.6");
|
||||
println!(" ██╔██╗ ██║█████╗ ██║ ██║██████╔╝██║ ██║ interactive harness");
|
||||
println!(" ██║╚██╗██║██╔══╝ ██║ ██║██╔══██╗██║ ██║ by Joas A Santos");
|
||||
println!(" ██║ ╚████║███████╗╚██████╔╝██║ ██║╚██████╔╝ & Red Team Leaders");
|
||||
@@ -1626,12 +1630,9 @@ fn browse_results(history: &[RunRecord]) {
|
||||
};
|
||||
print_finding_detail(&f[fi]);
|
||||
// Enter → back to the vuln list; Esc → back to the target list.
|
||||
match dialoguer::Select::with_theme(&ColorfulTheme::default())
|
||||
if let Ok(None) = dialoguer::Select::with_theme(&ColorfulTheme::default())
|
||||
.with_prompt("↵ back to vulnerabilities · Esc = back to targets")
|
||||
.items(&["back"]).default(0).interact_opt() {
|
||||
Ok(None) => break,
|
||||
_ => {}
|
||||
}
|
||||
.items(&["back"]).default(0).interact_opt() { break }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2118,7 +2119,7 @@ fn attach_path(spec: &str, s: &mut Session) -> usize {
|
||||
Ok(content) => {
|
||||
let body = match range.and_then(parse_range) {
|
||||
Some((a, b)) => content.lines().enumerate()
|
||||
.filter(|(i, _)| *i + 1 >= a && *i + 1 <= b)
|
||||
.filter(|(i, _)| *i + 1 >= a && *i < b)
|
||||
.map(|(_, l)| l).collect::<Vec<_>>().join("\n"),
|
||||
None => content.chars().take(8000).collect(),
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//! NeuroSploit v3.6.5 — TUI "Mission Control" mode.
|
||||
//! NeuroSploit v3.6.6 — 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:
|
||||
@@ -169,7 +169,7 @@ pub async fn run(base: &Path, mut cfg: RunConfig, mcp: bool, mode: Mode) -> anyh
|
||||
}
|
||||
});
|
||||
|
||||
let out;
|
||||
|
||||
loop {
|
||||
// drain engagement events
|
||||
while let Ok(line) = rx.try_recv() { ui.ingest(line); }
|
||||
@@ -206,17 +206,14 @@ pub async fn run(base: &Path, mut cfg: RunConfig, mcp: bool, mode: Mode) -> anyh
|
||||
}
|
||||
}
|
||||
|
||||
out = (&mut task).await.unwrap_or_default();
|
||||
let out = (&mut task).await.unwrap_or_default();
|
||||
|
||||
// ---- restore terminal ----
|
||||
execute!(stdout(), terminal::LeaveAlternateScreen)?;
|
||||
terminal::disable_raw_mode()?;
|
||||
|
||||
// generate report unless discarded; print a plain summary after leaving the TUI
|
||||
match harness::report::typst_report(&out.target, &out.findings, &workdir) {
|
||||
Ok(p) => println!(" report → {}", p.display()),
|
||||
Err(_) => {}
|
||||
}
|
||||
if let Ok(p) = harness::report::typst_report(&out.target, &out.findings, &workdir) { println!(" report → {}", p.display()) }
|
||||
crate::write_status_pub(&workdir, if cancel.load(Ordering::Relaxed) { "stopped" } else { "complete" }, "");
|
||||
println!(" ✓ {} validated finding(s) · {}", out.findings.len(), workdir.display());
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user