NeuroSploit v3.2.4 - MD Agent Orchestrator Overhaul + Claude 4.6 + SmartRouter Failover

- MD Agent system restructured: real HTTP exploitation, retry with exponential backoff, reduced concurrency (2 parallel, 2s stagger)
- Claude 4.6 model support (Opus/Sonnet) with corrected API version headers
- SmartRouter true failover with provider preference cascade
- WAFResult attribute error fix in autonomous_agent.py
- CVSS data sanitization for all vulnerability database saves
- AI recon JSON parsing robustness improvements
- rebuild.sh simplified from 714 to 196 lines
- Frontend: removed unused routes, simplified Auto Pentest page
- Agent grid: reduced max tests per agent (8→5), condensed recon prompts

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
CyberSecurityUP
2026-03-29 20:25:01 -03:00
parent 7563260b2b
commit 59f8f42d80
18 changed files with 1184 additions and 1367 deletions
-12
View File
@@ -34,18 +34,12 @@ data/*.db
data/*.db.*
data/execution_history.json
data/access_control_learning.json
data/adaptive_learning.json
data/providers.json
data/reasoning_memory.json
data/vectorstore/
data/custom-knowledge/uploads/
data/reports/
# ==============================
# Reports & Screenshots
# ==============================
reports/screenshots/
reports/*.json
# ==============================
# Logs & PIDs
@@ -84,9 +78,3 @@ docker/*.env
# Results (runtime output)
# ==============================
results/
# ==============================
# Large binary files
# ==============================
projeto.zip
*.zip
+32 -11
View File
@@ -18,6 +18,27 @@ from datetime import datetime
from enum import Enum
from urllib.parse import urlparse
def _safe_cvss_score(val) -> float:
"""Sanitize cvss_score: convert to float, default 0.0 for non-numeric."""
if val is None:
return 0.0
if isinstance(val, (int, float)):
return float(val)
try:
return float(val)
except (ValueError, TypeError):
return 0.0
def _safe_cvss_vector(val) -> str:
"""Sanitize cvss_vector: return empty string for N/A or invalid values."""
if not val or not isinstance(val, str):
return ""
if val.strip().upper().startswith("N/A") or len(val.strip()) < 5:
return ""
return val[:100]
from backend.core.autonomous_agent import AutonomousAgent, OperationMode
from backend.core.task_library import get_task_library
from backend.db.database import async_session_factory
@@ -123,7 +144,7 @@ class AgentRequest(BaseModel):
enable_kali_sandbox: bool = Field(False, description="Enable Kali Linux sandbox for tool execution + AI researcher")
custom_prompt_ids: Optional[List[str]] = Field(None, description="IDs of custom prompts to include in agent flow")
preferred_provider: Optional[str] = Field(None, description="Preferred LLM provider (e.g., 'anthropic', 'gemini_cli', 'openai')")
preferred_model: Optional[str] = Field(None, description="Preferred model name (e.g., 'claude-sonnet-4-20250514', 'gemini-2.0-flash')")
preferred_model: Optional[str] = Field(None, description="Preferred model name (e.g., 'claude-sonnet-4-6-20250918', 'claude-opus-4-6-20250918', 'gemini-2.0-flash')")
methodology_file: Optional[str] = Field(None, description="Path to external .md methodology file to inject into all AI calls")
enable_cli_agent: bool = Field(False, description="Enable CLI Agent (AI CLI inside Kali sandbox)")
cli_agent_provider: Optional[str] = Field(None, description="CLI provider: claude_code, gemini_cli, codex_cli")
@@ -431,8 +452,8 @@ async def _run_agent_task(
title=finding.get("title", finding.get("type", "Unknown")),
vulnerability_type=finding.get("vulnerability_type", finding.get("type", "unknown")),
severity=severity,
cvss_score=finding.get("cvss_score"),
cvss_vector=finding.get("cvss_vector"),
cvss_score=_safe_cvss_score(finding.get("cvss_score")),
cvss_vector=_safe_cvss_vector(finding.get("cvss_vector")),
cwe_id=finding.get("cwe_id"),
description=finding.get("description") or finding.get("evidence") or "",
affected_endpoint=finding.get("affected_endpoint", finding.get("endpoint", finding.get("url", target))),
@@ -463,8 +484,8 @@ async def _run_agent_task(
title=finding.get("title", finding.get("type", "Unknown")),
vulnerability_type=finding.get("vulnerability_type", finding.get("type", "unknown")),
severity=finding.get("severity", "medium").lower(),
cvss_score=finding.get("cvss_score"),
cvss_vector=finding.get("cvss_vector"),
cvss_score=_safe_cvss_score(finding.get("cvss_score")),
cvss_vector=_safe_cvss_vector(finding.get("cvss_vector")),
cwe_id=finding.get("cwe_id"),
description=finding.get("description") or finding.get("evidence") or "",
affected_endpoint=finding.get("affected_endpoint", finding.get("endpoint", finding.get("url", target))),
@@ -916,8 +937,8 @@ async def stop_agent(agent_id: str):
title=finding.get("title", finding.get("type", "Unknown")),
vulnerability_type=finding.get("vulnerability_type", finding.get("type", "unknown")),
severity=severity,
cvss_score=finding.get("cvss_score"),
cvss_vector=finding.get("cvss_vector"),
cvss_score=_safe_cvss_score(finding.get("cvss_score")),
cvss_vector=_safe_cvss_vector(finding.get("cvss_vector")),
cwe_id=finding.get("cwe_id"),
description=finding.get("description") or finding.get("evidence") or "",
affected_endpoint=finding.get("affected_endpoint", finding.get("endpoint", finding.get("url", target))),
@@ -949,8 +970,8 @@ async def stop_agent(agent_id: str):
title=finding.get("title", finding.get("type", "Unknown")),
vulnerability_type=finding.get("vulnerability_type", finding.get("type", "unknown")),
severity=finding.get("severity", "medium").lower(),
cvss_score=finding.get("cvss_score"),
cvss_vector=finding.get("cvss_vector"),
cvss_score=_safe_cvss_score(finding.get("cvss_score")),
cvss_vector=_safe_cvss_vector(finding.get("cvss_vector")),
cwe_id=finding.get("cwe_id"),
description=finding.get("description") or finding.get("evidence") or "",
affected_endpoint=finding.get("affected_endpoint", finding.get("endpoint", finding.get("url", target))),
@@ -2493,8 +2514,8 @@ async def _save_realtime_findings_to_db(session_id: str, session: Dict):
title=title,
vulnerability_type=finding.get("vulnerability_type", "unknown"),
severity=severity,
cvss_score=finding.get("cvss_score"),
cvss_vector=finding.get("cvss_vector"),
cvss_score=_safe_cvss_score(finding.get("cvss_score")),
cvss_vector=_safe_cvss_vector(finding.get("cvss_vector")),
cwe_id=finding.get("cwe_id"),
description=finding.get("description") or finding.get("evidence") or "",
affected_endpoint=finding.get("affected_endpoint", target),
+6 -2
View File
@@ -155,6 +155,7 @@ async def test_connection(provider_id: str, account_id: str):
PROVIDER_MODELS = {
"claude_code": [
"claude-opus-4-6-20250918",
"claude-sonnet-4-6-20250918",
"claude-sonnet-4-5-20250929",
"claude-haiku-4-5-20251001",
"claude-sonnet-4-20250514",
@@ -163,6 +164,7 @@ PROVIDER_MODELS = {
],
"kiro": [
"claude-opus-4-6-20250918",
"claude-sonnet-4-6-20250918",
"claude-sonnet-4-5-20250929",
"claude-haiku-4-5-20251001",
"claude-sonnet-4-20250514",
@@ -171,6 +173,7 @@ PROVIDER_MODELS = {
],
"anthropic": [
"claude-opus-4-6-20250918",
"claude-sonnet-4-6-20250918",
"claude-sonnet-4-5-20250929",
"claude-haiku-4-5-20251001",
"claude-sonnet-4-20250514",
@@ -214,17 +217,18 @@ PROVIDER_MODELS = {
"cursor-fast",
"cursor-small",
"gpt-4o",
"claude-sonnet-4-6-20250918",
"claude-sonnet-4-5-20250929",
"claude-3-5-sonnet-20241022",
],
"copilot": [
"gpt-4o",
"gpt-4o-mini",
"claude-sonnet-4-6-20250918",
"claude-sonnet-4-5-20250929",
"claude-3-5-sonnet-20241022",
],
"openrouter": [
"anthropic/claude-opus-4-6",
"anthropic/claude-sonnet-4-6",
"anthropic/claude-sonnet-4-5",
"anthropic/claude-haiku-4-5",
"anthropic/claude-sonnet-4",
+4 -1
View File
@@ -533,9 +533,12 @@ MODEL_CACHE_TTL = 60 # seconds
# Common cloud models for dropdown suggestions
CLOUD_MODELS = {
"claude": [
{"model_id": "claude-opus-4-6-20250918", "display_name": "Claude Opus 4.6", "context_length": 1000000},
{"model_id": "claude-sonnet-4-6-20250918", "display_name": "Claude Sonnet 4.6", "context_length": 1000000},
{"model_id": "claude-sonnet-4-5-20250929", "display_name": "Claude Sonnet 4.5", "context_length": 200000},
{"model_id": "claude-haiku-4-5-20251001", "display_name": "Claude Haiku 4.5", "context_length": 200000},
{"model_id": "claude-sonnet-4-20250514", "display_name": "Claude Sonnet 4", "context_length": 200000},
{"model_id": "claude-opus-4-20250514", "display_name": "Claude Opus 4", "context_length": 200000},
{"model_id": "claude-haiku-4-20250514", "display_name": "Claude Haiku 4", "context_length": 200000},
],
"openai": [
{"model_id": "gpt-4o", "display_name": "GPT-4o", "context_length": 128000},
+139 -222
View File
@@ -3921,6 +3921,7 @@ NOT_VULNERABLE: <reason>"""
)
# Phase 5.5: MD-based agent orchestrator (always available)
# Agents execute REAL HTTP requests via the shared aiohttp session
if HAS_MD_AGENTS:
self._md_orchestrator = MdAgentOrchestrator(
llm=self.llm,
@@ -3929,6 +3930,9 @@ NOT_VULNERABLE: <reason>"""
validation_judge=self.validation_judge,
log_callback=self.log,
progress_callback=self.progress_callback,
http_session=self.session,
auth_headers=dict(self.auth_headers),
cancel_fn=self.is_cancelled,
)
# Researcher AI: 0-day discovery with Kali sandbox (opt-in)
@@ -4630,55 +4634,24 @@ NOT_VULNERABLE: <reason>"""
await self.log("warning", f" Sandbox scan error: {e}")
async def _run_auto_pentest(self) -> Dict:
"""Parallel auto pentest: 3 concurrent streams + deep analysis + report.
"""Agent-first auto pentest: Recon → 108 AI agents with real HTTP → Report.
Architecture:
Stream 1 (Recon) asyncio.Queue Stream 2 (Junior Pentester)
Stream 3 (Tool Runner) runs sandbox tools + AI-decided tools
All streams feed findings in real-time via callbacks.
After parallel phase completes:
Deep Analysis: AI attack surface analysis + comprehensive 100-type testing
Finalization: Screenshots + AI enhancement + report generation
Phase 1 (0-20%): Quick recon discover endpoints, tech, params, WAF
Phase 2 (20-85%): Agent Grid 108 agents execute real HTTP tests
Phase 3 (85-100%): Finalization screenshots, enhancement, report
"""
await self._update_progress(0, "Auto pentest starting")
await self.log("info", "=" * 60)
await self.log("info", " PARALLEL AUTO PENTEST MODE")
await self.log("info", " 3 concurrent streams | AI-powered | 100 vuln types")
await self.log("info", " AGENT-FIRST AUTO PENTEST (108 AGENTS)")
await self.log("info", " Recon → Agent Grid (real HTTP) → Report | Claude 4.6")
await self.log("info", "=" * 60)
# Override custom_prompt with DEFAULT_ASSESSMENT_PROMPT for auto mode
if not self.custom_prompt:
self.custom_prompt = DEFAULT_ASSESSMENT_PROMPT
# Phase 5: Multi-agent orchestrator (if enabled, replaces 3-stream)
if self._orchestrator:
await self.log("info", " [MULTI-AGENT] Orchestrator enabled — delegating to specialist agents")
orch_result = await self._orchestrator.run(
target=self.target,
recon_data=self.recon,
initial_context={
"headers": dict(self.auth_headers),
"technologies": self.recon.technologies,
}
)
# Merge orchestrator findings into agent findings
for f in orch_result.get("findings", []):
if isinstance(f, Finding):
await self._add_finding(f)
await self.log("info", f" [MULTI-AGENT] Pipeline complete: "
f"{orch_result.get('findings_count', 0)} findings")
# Continue to finalization phase below
report = await self._generate_full_report()
await self._update_progress(100, "Multi-agent pentest complete")
if hasattr(self, 'execution_history') and self.execution_history:
self.execution_history.flush()
await self.log("info", "=" * 60)
await self.log("info", f" AUTO PENTEST COMPLETE: {len(self.findings)} findings")
await self.log("info", "=" * 60)
return report
# Shared state for parallel streams
# Shared state (needed by some helper methods)
self._endpoint_queue = asyncio.Queue()
self._recon_complete = asyncio.Event()
self._tools_complete = asyncio.Event()
@@ -4686,133 +4659,49 @@ NOT_VULNERABLE: <reason>"""
self._junior_tested_types: set = set()
self._playbook_recommended_types: List[str] = []
self._current_playbook_context: str = ""
# ── PRE-STREAM AI MASTER PLAN ──
# Before launching parallel streams, ask AI for a strategic master plan
# that provides context and direction for all 3 streams.
self._master_plan: Dict = {}
if self.llm.is_available():
try:
await self.log("info", "[MASTER PLAN] AI strategic planning before streams")
master_plan = await self._ai_master_plan()
if master_plan:
self._master_plan = master_plan
profile = master_plan.get("target_profile", "")
risk = master_plan.get("risk_assessment", "")
priority_types = master_plan.get("priority_vuln_types", [])
if profile:
await self.log("info", f" [MASTER PLAN] Profile: {profile[:120]}")
if risk:
await self.log("info", f" [MASTER PLAN] Risk: {risk[:120]}")
if priority_types:
await self.log("info", f" [MASTER PLAN] Priority: {', '.join(priority_types[:8])}")
except Exception as e:
await self.log("debug", f" [MASTER PLAN] Planning error: {e}")
# ── CONCURRENT PHASE (0-50%): 3 parallel streams ──
await asyncio.gather(
self._stream_recon(), # Stream 1: Recon pipeline
self._stream_junior_pentest(), # Stream 2: Immediate AI testing
self._stream_tool_runner(), # Stream 3: Dynamic tool execution
)
# ══════════════════════════════════════════════════════════════
# PHASE 1 (0-20%): RECONNAISSANCE
# Discover attack surface before dispatching agents
# ══════════════════════════════════════════════════════════════
await self.log("info", "[RECON] Mapping attack surface...")
await self._update_progress(2, "Recon: mapping attack surface")
parallel_findings = len(self.findings)
await self.log("info", f" Parallel phase complete: {parallel_findings} findings, "
f"{len(self._junior_tested_types)} types pre-tested")
await self._update_progress(50, "Parallel streams complete")
# Run recon stream (endpoint discovery, tech detection, site analysis)
self._recon_complete.clear()
self._tools_complete.set() # No tool stream in agent-first mode
await self._stream_recon()
# ── REASONING CHECKPOINT at 30-50% ──
if self.reasoning_engine and self.llm.is_available():
try:
plan = await self.reasoning_engine.plan_attack(
recon_summary=f"{len(self.recon.endpoints)} endpoints, "
f"{len(self.recon.technologies)} techs",
findings_so_far=self.findings,
tested_types=self._junior_tested_types,
progress_pct=0.50,
ep_count = len(self.recon.endpoints)
param_count = len(self.recon.parameters) if isinstance(self.recon.parameters, dict) else 0
tech_count = len(self.recon.technologies)
form_count = len(self.recon.forms) if hasattr(self.recon, 'forms') else 0
js_count = len(self.recon.js_files) if hasattr(self.recon, 'js_files') else 0
sink_count = len(self.recon.js_sinks) if hasattr(self.recon, 'js_sinks') else 0
api_count = len(self.recon.api_endpoints) if hasattr(self.recon, 'api_endpoints') else 0
await self.log("info",
f"[RECON] Complete: {ep_count} endpoints, {param_count} params, "
f"{tech_count} techs, {form_count} forms, {js_count} JS files, "
f"{sink_count} sinks, {api_count} API endpoints")
await self._update_progress(15, "Recon complete")
# WAF info for agents
waf_name = ""
if hasattr(self, '_waf_result') and self._waf_result:
if hasattr(self._waf_result, 'detected_wafs') and self._waf_result.detected_wafs:
waf_name = ", ".join(
f"{w.name} ({w.confidence:.0%})" for w in self._waf_result.detected_wafs
)
if plan and plan.priority_vulns:
await self.log("info", f" [REASONING] Attack plan: "
f"focus on {', '.join(plan.priority_vulns[:5])}")
# Feed reasoning priorities into the remaining test plan
for vtype in plan.priority_vulns:
if vtype not in self._junior_tested_types:
self._junior_tested_types.discard(vtype) # ensure retested
except Exception as e:
await self.log("debug", f" [REASONING] Plan error: {e}")
elif isinstance(self._waf_result, dict):
waf_name = self._waf_result.get("waf_name", "")
if waf_name:
await self.log("warning", f"[WAF] Detected: {waf_name} — agents will adapt payloads")
# ── STRATEGY CHECKPOINT at 50% ──
if self.strategy:
try:
strat_update = await self.strategy.checkpoint_refine(
progress_pct=0.50,
findings=self.findings,
tested_types=self._junior_tested_types,
all_endpoints=[ep for ep in self.recon.endpoints],
llm=self.llm if self.llm.is_available() else None,
budget=self.token_budget,
)
if strat_update.get("message"):
await self.log("info", f" [STRATEGY] {strat_update['message']}")
except Exception as e:
await self.log("debug", f" [STRATEGY] Checkpoint error: {e}")
# ── DEEP ANALYSIS PHASE (50-75%): Full testing with complete context ──
await self.log("info", "[DEEP] AI Attack Surface Analysis + Comprehensive Testing")
attack_plan = await self._ai_analyze_attack_surface()
# Merge AI-recommended types with default plan + playbook recommendations
default_plan = self._default_attack_plan()
ai_types = attack_plan.get("priority_vulns", [])
playbook_types = self._playbook_recommended_types[:15] if self._playbook_recommended_types else []
all_types = default_plan["priority_vulns"]
merged_types = list(dict.fromkeys(ai_types + playbook_types + all_types))
# Remove types already tested by junior pentest stream
remaining = [t for t in merged_types if t not in self._junior_tested_types]
attack_plan["priority_vulns"] = remaining
await self.log("info", f" {len(remaining)} remaining types "
f"({len(self._junior_tested_types)} already tested by junior)")
await self._update_progress(55, "Deep: attack surface analyzed")
await self.log("info", "[DEEP] Comprehensive Vulnerability Testing")
await self._test_all_vulnerabilities(attack_plan)
await self._update_progress(75, "Deep testing complete")
# ── REASONING CHECKPOINT at 75% ──
if self.reasoning_engine and self.llm.is_available():
try:
plan = await self.reasoning_engine.plan_attack(
recon_summary=f"{len(self.recon.endpoints)} endpoints, "
f"{len(self.recon.technologies)} techs",
findings_so_far=self.findings,
tested_types=self._junior_tested_types,
progress_pct=0.75,
)
if plan and plan.priority_vulns:
await self.log("info", f" [REASONING] 75% plan: "
f"focus on {', '.join(plan.priority_vulns[:5])}")
# Reflect on what worked so far
try:
reflection = await self.reasoning_engine.reflect(
action_taken="deep_testing_phase",
result_observed={
"findings_count": len(self.findings),
"tested_types": len(self._junior_tested_types),
"endpoints": len(self.recon.endpoints),
}
)
if reflection and reflection.next_suggestion:
await self.log("info", f" [REASONING] Reflection: {reflection.next_suggestion}")
except Exception:
pass
except Exception as e:
await self.log("debug", f" [REASONING] 75% plan error: {e}")
# ── CVE HUNTING (if we found versions during recon) ──
# CVE hunting (quick, parallel with next phase)
if self.cve_hunter and self.recon.technologies:
try:
await self.log("info", "[CVE] Searching for known CVEs based on detected versions")
cve_findings = await self.cve_hunter.hunt(
headers=dict(self.auth_headers),
body="",
@@ -4824,7 +4713,77 @@ NOT_VULNERABLE: <reason>"""
except Exception as e:
await self.log("debug", f" [CVE] Hunt error: {e}")
# ── AI CHAIN DISCOVERY ──
await self._update_progress(20, "Recon + CVE complete, launching agents")
# ══════════════════════════════════════════════════════════════
# PHASE 2 (20-85%): AGENT GRID — 108 SPECIALISTS WITH REAL HTTP
# Each agent: LLM plans attacks → executes HTTP → LLM analyzes
# ══════════════════════════════════════════════════════════════
if self._md_orchestrator and not self.is_cancelled():
try:
n_available = len(self._md_orchestrator.library.agents)
await self.log("info", "=" * 60)
await self.log("info", f" [AGENT GRID] Dispatching {n_available} specialist agents")
await self.log("info", f" Each agent: PLAN (LLM) → EXECUTE (HTTP) → ANALYZE (LLM)")
await self.log("info", "=" * 60)
md_result = await self._md_orchestrator.run(
target=self.target,
recon_data=self.recon,
existing_findings=self.findings,
selected_agents=self.selected_md_agents,
headers=dict(self.auth_headers),
waf_info=waf_name,
)
# Merge agent findings into main findings via validation pipeline
md_findings_raw = md_result.get("findings", [])
md_confirmed = 0
for mf in md_findings_raw:
if self.is_cancelled():
break
if not isinstance(mf, dict):
continue
try:
finding = Finding(
id=str(hashlib.md5(
f"{mf.get('title', '')}{mf.get('affected_endpoint', '')}".encode()
).hexdigest())[:12],
title=mf.get("title", "Agent Finding"),
severity=mf.get("severity", "medium"),
vulnerability_type=mf.get("vulnerability_type", "unknown"),
cvss_score=float(mf.get("cvss_score", 0.0)) if isinstance(mf.get("cvss_score"), (int, float)) else 0.0,
cwe_id=mf.get("cwe_id", ""),
description=mf.get("description", ""),
affected_endpoint=mf.get("affected_endpoint", self.target),
evidence=mf.get("evidence", ""),
poc_code=mf.get("poc_code", ""),
impact=mf.get("impact", ""),
remediation=mf.get("remediation", ""),
confidence_score={"high": 80, "medium": 50, "low": 25}.get(mf.get("confidence", "medium"), 50),
confidence=mf.get("confidence", "medium"),
ai_verified=mf.get("confidence") == "high",
ai_status="confirmed" if mf.get("confidence") == "high" else "pending",
)
await self._add_finding(finding)
md_confirmed += 1
except Exception as e:
await self.log("debug", f" [AGENT GRID] Finding merge error: {e}")
agents_run = md_result.get("agents_run", 0)
duration = md_result.get("duration", 0)
await self.log("info",
f"[AGENT GRID] Complete: {agents_run} agents, "
f"{len(md_findings_raw)} raw findings, "
f"{md_confirmed} validated, {duration}s")
except Exception as e:
await self.log("warning", f"[AGENT GRID] Dispatch error: {e}")
else:
await self.log("warning", "[AGENT GRID] MD agent system not available")
await self._update_progress(80, "Agent grid complete")
# ── AI CHAIN DISCOVERY (post-agents, if we have findings) ──
if self.chain_engine and len(self.findings) >= 2 and self.llm.is_available():
try:
chains = await self.chain_engine.ai_discover_chains(
@@ -4838,66 +4797,7 @@ NOT_VULNERABLE: <reason>"""
except Exception as e:
await self.log("debug", f" [CHAIN] AI discovery error: {e}")
# ── MD-BASED AGENT DISPATCH (post-recon specialist agents) ──
if self._md_orchestrator and not self.is_cancelled():
try:
await self.log("info", "[MD-AGENTS] Dispatching specialist .md agents with recon context")
md_result = await self._md_orchestrator.run(
target=self.target,
recon_data=self.recon,
existing_findings=self.findings,
selected_agents=self.selected_md_agents,
headers=dict(self.auth_headers),
waf_info=(
self._waf_result.get("waf_name", "")
if self._waf_result else ""
),
)
# Merge MD agent findings into main findings via validation
md_findings_raw = md_result.get("findings", [])
md_confirmed = 0
for mf in md_findings_raw:
if self.is_cancelled():
break
if not isinstance(mf, dict):
continue
try:
finding = Finding(
id=str(hashlib.md5(
f"{mf.get('title', '')}{mf.get('affected_endpoint', '')}".encode()
).hexdigest())[:12],
title=mf.get("title", "MD Agent Finding"),
severity=mf.get("severity", "medium"),
vulnerability_type=mf.get("vulnerability_type", "unknown"),
cvss_score=mf.get("cvss_score", 0.0),
cwe_id=mf.get("cwe_id", ""),
description=mf.get("description", ""),
affected_endpoint=mf.get("affected_endpoint", self.target),
evidence=mf.get("evidence", ""),
poc_code=mf.get("poc_code", ""),
impact=mf.get("impact", ""),
remediation=mf.get("remediation", ""),
confidence_score=50,
confidence="medium",
ai_verified=False,
ai_status="pending",
)
# Flow through validation pipeline
await self._add_finding(finding)
md_confirmed += 1
except Exception as e:
await self.log("debug", f" [MD-AGENTS] Finding merge error: {e}")
agent_summary = md_result.get("agent_results", {})
agents_run = md_result.get("agents_run", 0)
await self.log("info",
f"[MD-AGENTS] Complete: {agents_run} agents, "
f"{len(md_findings_raw)} raw findings, "
f"{md_confirmed} submitted to validation, "
f"{md_result.get('duration', 0)}s")
except Exception as e:
await self.log("warning", f"[MD-AGENTS] Dispatch error: {e}")
await self._update_progress(85, "Chain analysis complete")
# ── RESEARCHER AI (0-day discovery with Kali sandbox) ──
if self._researcher and not self.is_cancelled():
@@ -6043,11 +5943,28 @@ NOT_VULNERABLE: <reason>"""
prompt,
system=self._get_enhanced_system_prompt("strategy")
)
start = resp_text.index('{')
end = resp_text.rindex('}') + 1
return json.loads(resp_text[start:end])
if not resp_text or len(resp_text.strip()) < 20:
await self.log("debug", " [AI RECON] Empty or too short response from LLM")
return {}
# Try to find JSON in response
json_match = re.search(r'```(?:json)?\s*(\{[\s\S]*?\})\s*```', resp_text)
if json_match:
return json.loads(json_match.group(1))
# Try bare JSON
start = resp_text.find('{')
end = resp_text.rfind('}')
if start >= 0 and end > start:
return json.loads(resp_text[start:end + 1])
await self.log("debug", " [AI RECON] No JSON found in LLM response")
return {}
except json.JSONDecodeError as e:
await self.log("debug", f" [AI RECON] JSON parse error: {e}")
return {}
except Exception as e:
await self.log("debug", f" [AI RECON] Parse error: {e}")
await self.log("debug", f" [AI RECON] Analysis error: {e}")
return {}
# ── Stream 2: Junior Pentester ──
+755 -387
View File
File diff suppressed because it is too large Load Diff
@@ -81,7 +81,7 @@ DEFAULT_PROVIDERS: List[Dict] = [
{
"id": "claude_code", "name": "Claude Code", "auth_type": "oauth",
"api_format": "anthropic", "base_url": "https://api.anthropic.com",
"tier": 1, "default_model": "claude-sonnet-4-5-20250929",
"tier": 1, "default_model": "claude-sonnet-4-20250514",
},
{
"id": "codex_cli", "name": "OpenAI Codex CLI", "auth_type": "oauth",
@@ -116,13 +116,13 @@ DEFAULT_PROVIDERS: List[Dict] = [
{
"id": "kiro", "name": "Kiro AI", "auth_type": "oauth",
"api_format": "anthropic", "base_url": "https://api.anthropic.com",
"tier": 1, "default_model": "claude-sonnet-4-5-20250929",
"tier": 1, "default_model": "claude-sonnet-4-20250514",
},
# === API Key Providers (Tier 1 - Paid) ===
{
"id": "anthropic", "name": "Anthropic", "auth_type": "api_key",
"api_format": "anthropic", "base_url": "https://api.anthropic.com",
"tier": 1, "default_model": "claude-sonnet-4-5-20250929",
"tier": 1, "default_model": "claude-sonnet-4-20250514",
"env_key": "ANTHROPIC_API_KEY",
},
{
@@ -140,7 +140,7 @@ DEFAULT_PROVIDERS: List[Dict] = [
{
"id": "openrouter", "name": "OpenRouter", "auth_type": "api_key",
"api_format": "openai_compat", "base_url": "https://openrouter.ai/api/v1",
"tier": 1, "default_model": "anthropic/claude-sonnet-4-5",
"tier": 1, "default_model": "anthropic/claude-sonnet-4-20250514",
"env_key": "OPENROUTER_API_KEY",
},
# === API Key Providers (Tier 2 - Cheap) ===
+8 -8
View File
@@ -173,41 +173,41 @@ class SmartRouter:
) -> List[Tuple[Provider, Account]]:
"""Build ordered list of (provider, account) candidates.
If preferred is set, ONLY that provider is used (no fallback to others).
This ensures the user's explicit choice is respected.
If preferred is set, that provider is tried FIRST, then falls back
to other providers of the same tier if all accounts fail.
If preferred is not set, all providers are tried by tier.
"""
candidates = []
seen_account_ids = set()
if preferred:
# Strict mode: only the preferred provider
# Preferred provider goes first in candidate list
provider = self.registry.get_provider(preferred)
if provider:
accounts = self.registry.get_active_accounts(preferred)
for acct in accounts:
if self.quota.is_available(acct.id):
candidates.append((provider, acct))
seen_account_ids.add(acct.id)
if not candidates:
logger.warning(
f"SmartRouter: Preferred provider '{preferred}' has no active accounts! "
f"Falling back to all providers."
)
else:
return candidates # Only preferred provider candidates
# Auto mode or preferred has no active accounts: try all by tier
# Add remaining providers as fallback (by tier)
for tier in (1, 2, 3):
providers = self.registry.get_providers_by_tier(tier)
for provider in providers:
# Skip disabled providers
if not getattr(provider, "enabled", True):
continue
acct = self.quota.next_account(
provider.id,
self.registry.get_active_accounts(provider.id),
)
if acct:
if acct and acct.id not in seen_account_ids:
candidates.append((provider, acct))
seen_account_ids.add(acct.id)
return candidates
+1 -2
View File
@@ -11,7 +11,7 @@ from pathlib import Path
from backend.config import settings
from backend.db.database import init_db, close_db
from backend.api.v1 import scans, targets, prompts, reports, dashboard, vulnerabilities, settings as settings_router, agent, agent_tasks, scheduler, vuln_lab, terminal, sandbox, knowledge, mcp, providers, full_ia, cli_agent
from backend.api.v1 import scans, targets, prompts, reports, dashboard, vulnerabilities, settings as settings_router, agent, agent_tasks, scheduler, vuln_lab, terminal, sandbox, knowledge, mcp, providers, cli_agent
from backend.api.websocket import manager as ws_manager
@@ -116,7 +116,6 @@ app.include_router(sandbox.router, prefix="/api/v1/sandbox", tags=["Sandbox"])
app.include_router(knowledge.router, prefix="/api/v1/knowledge", tags=["Knowledge"])
app.include_router(mcp.router, prefix="/api/v1/mcp", tags=["MCP Servers"])
app.include_router(providers.router, prefix="/api/v1/providers", tags=["Providers"])
app.include_router(full_ia.router, prefix="/api/v1/full-ia", tags=["FULL AI Testing"])
app.include_router(cli_agent.router)
+4 -4
View File
@@ -32,12 +32,12 @@
},
"claude_opus_default": {
"provider": "claude",
"model": "claude-3-opus-20240229",
"model": "claude-opus-4-6-20250918",
"api_key": "${ANTHROPIC_API_KEY}",
"temperature": 0.7,
"max_tokens": 4096,
"input_token_limit": 200000,
"output_token_limit": 4096,
"max_tokens": 16384,
"input_token_limit": 1000000,
"output_token_limit": 16384,
"cache_enabled": true,
"search_context_level": "high",
"pdf_support_enabled": true,
+1 -1
View File
@@ -649,7 +649,7 @@ Identify any potential hallucinations, inconsistencies, or areas where the respo
"""Generate using OpenRouter API (OpenAI-compatible).
OpenRouter supports hundreds of models through a unified API.
Models are specified as provider/model (e.g., 'anthropic/claude-sonnet-4-20250514').
Models are specified as provider/model (e.g., 'anthropic/claude-sonnet-4-6').
API key comes from OPENROUTER_API_KEY env var or config profile.
"""
if not self.api_key:
-3
View File
@@ -17,15 +17,12 @@ import SandboxDashboardPage from './pages/SandboxDashboardPage'
import KnowledgePage from './pages/KnowledgePage'
import MCPManagementPage from './pages/MCPManagementPage'
import ProvidersPage from './pages/ProvidersPage'
import FullIATestingPage from './pages/FullIATestingPage'
function App() {
return (
<Layout>
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/auto" element={<AutoPentestPage />} />
<Route path="/full-ia" element={<FullIATestingPage />} />
<Route path="/vuln-lab" element={<VulnLabPage />} />
<Route path="/terminal" element={<TerminalAgentPage />} />
<Route path="/scan/new" element={<NewScanPage />} />
+2 -1
View File
@@ -5,7 +5,8 @@ const pageTitles: Record<string, string> = {
'/scan/new': 'New Security Scan',
'/reports': 'Reports',
'/settings': 'Settings',
'/full-ia': 'FULL AI TESTING',
'/auto': 'Auto Pentest',
'/realtime': 'Real-time Task',
}
export default function Header() {
@@ -16,7 +16,6 @@ import {
Brain,
Cable,
Plug,
Crosshair,
ChevronLeft,
ChevronRight,
} from 'lucide-react'
@@ -30,7 +29,6 @@ const navGroups = [
{ path: '/auto', icon: Rocket, label: 'Auto Pentest' },
{ path: '/scan/new', icon: Bot, label: 'AI Agent' },
{ path: '/realtime', icon: Zap, label: 'Real-time Task' },
{ path: '/full-ia', icon: Crosshair, label: 'FULL AI TESTING' },
],
},
{
+77 -63
View File
@@ -14,15 +14,15 @@ import VulnAgentGrid from '../components/VulnAgentGrid'
// ─── Constants ────────────────────────────────────────────────────────────────
const PHASES = [
{ key: 'parallel', label: 'Parallel Streams', icon: Layers, range: [0, 50] as const },
{ key: 'deep', label: 'Deep Analysis', icon: Brain, range: [50, 75] as const },
{ key: 'final', label: 'Finalization', icon: Shield, range: [75, 100] as const },
{ key: 'recon', label: 'Reconnaissance', icon: Globe, range: [0, 20] as const },
{ key: 'agents', label: 'Agent Grid (108 agents)', icon: Layers, range: [20, 85] as const },
{ key: 'final', label: 'Finalization', icon: Shield, range: [85, 100] as const },
]
const STREAMS = [
{ key: 'recon', label: 'Recon', icon: Globe, color: 'blue', activeUntil: 25 },
{ key: 'junior', label: 'Junior AI', icon: Brain, color: 'purple', activeUntil: 35 },
{ key: 'tools', label: 'Tools', icon: Wrench, color: 'orange', activeUntil: 50 },
{ key: 'recon', label: 'Recon', icon: Globe, color: 'blue', activeUntil: 20 },
{ key: 'agents', label: 'Agent Grid', icon: Brain, color: 'purple', activeUntil: 85 },
{ key: 'final', label: 'Report', icon: Wrench, color: 'orange', activeUntil: 100 },
] as const
const STREAM_COLORS: Record<string, { bg: string; text: string; border: string; pulse: string }> = {
@@ -53,12 +53,10 @@ const CONFIDENCE_STYLES: Record<string, string> = {
const LOG_FILTERS = [
{ key: 'all', label: 'All', color: '' },
{ key: 'stream1', label: 'Recon', color: 'text-blue-400' },
{ key: 'stream2', label: 'Junior', color: 'text-purple-400' },
{ key: 'stream3', label: 'Tools', color: 'text-orange-400' },
{ key: 'deep', label: 'Deep', color: 'text-cyan-400' },
{ key: 'container', label: 'Container', color: 'text-cyan-300' },
{ key: 'cli_agent', label: 'CLI Agent', color: 'text-pink-400' },
{ key: 'recon', label: 'Recon', color: 'text-blue-400' },
{ key: 'agents', label: 'Agents', color: 'text-green-400' },
{ key: 'judge', label: 'Validation', color: 'text-amber-300' },
{ key: 'final', label: 'Final', color: 'text-cyan-400' },
{ key: 'error', label: 'Errors', color: 'text-red-400' },
]
@@ -88,8 +86,8 @@ interface Toast {
// ─── Utility Functions ────────────────────────────────────────────────────────
function phaseFromProgress(progress: number): number {
if (progress < 50) return 0
if (progress < 75) return 1
if (progress < 20) return 0
if (progress < 85) return 1
return 2
}
@@ -116,6 +114,15 @@ function logMessageColor(message: string): string {
if (message.startsWith('[PLAYBOOK]')) return 'text-indigo-400'
if (message.startsWith('[SITE ANALYZER]')) return 'text-emerald-400'
if (message.startsWith('[MD-AGENTS]')) return 'text-cyan-300'
if (message.startsWith('[AGENT GRID]')) return 'text-green-400'
if (message.startsWith('[PHASE 1]')) return 'text-blue-300'
if (message.startsWith('[PHASE 2]')) return 'text-purple-300'
if (message.startsWith('[PHASE 3]')) return 'text-yellow-300'
if (message.startsWith('[RECON]')) return 'text-blue-400'
if (message.startsWith('[CVE]')) return 'text-red-300'
if (message.startsWith('[CHAIN]')) return 'text-orange-300'
if (message.startsWith('[JUDGE]')) return 'text-amber-300'
if (message.includes('Starting (real HTTP)')) return 'text-green-300'
return ''
}
@@ -422,8 +429,8 @@ export default function AutoPentestPage() {
// Model selection
const [availableModels, setAvailableModels] = useState<Array<{ provider_id: string; provider_name: string; default_model: string; tier: number; available_models: string[] }>>([])
const [selectedProvider, setSelectedProvider] = useState('')
const [selectedModel, setSelectedModel] = useState('')
const [selectedProvider, setSelectedProvider] = useState('anthropic')
const [selectedModel, setSelectedModel] = useState('claude-sonnet-4-20250514')
// MD Agent selection
const [availableMdAgents, setAvailableMdAgents] = useState<Array<{ name: string; display_name: string; category: string }>>([])
@@ -739,12 +746,7 @@ export default function AutoPentestPage() {
return () => { if (pollRef.current) clearInterval(pollRef.current) }
}, [sessions, agentId, connectionLost, addToast])
// Auto-scroll logs
useEffect(() => {
if (activeTab === 'logs' && logsEndRef.current) {
logsEndRef.current.scrollIntoView({ behavior: 'smooth' })
}
}, [logs, activeTab])
// Auto-scroll logs disabled — user controls scroll position
// ─── History ──────────────────────────────────────────────────────────────
@@ -1376,48 +1378,60 @@ export default function AutoPentestPage() {
)}
{/* LLM Provider / Model Selection */}
{availableModels.length > 0 && (
<div className="mb-6 flex flex-col sm:flex-row gap-3 sm:gap-4">
<div className="flex-1">
<label className="block text-xs font-medium text-dark-400 mb-1">LLM Provider</label>
<select
value={selectedProvider}
onChange={e => {
setSelectedProvider(e.target.value)
const m = availableModels.find(m => m.provider_id === e.target.value)
if (m) setSelectedModel(m.default_model)
else setSelectedModel('')
}}
disabled={isRunning}
className="w-full px-3 py-2 bg-dark-900 border border-dark-600 rounded-lg text-sm text-white focus:outline-none focus:border-green-500 disabled:opacity-50 transition-colors"
>
<option value="">Auto (best available)</option>
{availableModels.map(m => (
<option key={m.provider_id} value={m.provider_id}>
{m.provider_name} (Tier {m.tier})
</option>
))}
</select>
</div>
<div className="flex-1">
<label className="block text-xs font-medium text-dark-400 mb-1">Model</label>
<select
value={selectedModel}
onChange={e => setSelectedModel(e.target.value)}
disabled={isRunning}
className="w-full px-3 py-2 bg-dark-900 border border-dark-600 rounded-lg text-sm text-white focus:outline-none focus:border-green-500 disabled:opacity-50 transition-colors"
>
<option value="">Auto (default)</option>
{(selectedProvider
? (availableModels.find(m => m.provider_id === selectedProvider)?.available_models || [])
: availableModels.flatMap(m => m.available_models).filter((v, i, a) => a.indexOf(v) === i)
).map(model => (
<option key={model} value={model}>{model}</option>
))}
</select>
</div>
<div className="mb-6 flex flex-col sm:flex-row gap-3 sm:gap-4">
<div className="flex-1">
<label className="block text-xs font-medium text-dark-400 mb-1">LLM Provider</label>
<select
value={selectedProvider}
onChange={e => {
setSelectedProvider(e.target.value)
const m = availableModels.find(m => m.provider_id === e.target.value)
if (m) setSelectedModel(m.default_model)
else if (e.target.value === 'anthropic') setSelectedModel('claude-sonnet-4-20250514')
else setSelectedModel('')
}}
disabled={isRunning}
className="w-full px-3 py-2 bg-dark-900 border border-dark-600 rounded-lg text-sm text-white focus:outline-none focus:border-green-500 disabled:opacity-50 transition-colors"
>
<option value="">Auto (best available)</option>
<option value="anthropic">Anthropic (Claude API)</option>
<option value="claude_code">Claude Code (OAuth)</option>
<option value="openai">OpenAI</option>
<option value="gemini">Gemini</option>
<option value="openrouter">OpenRouter</option>
{availableModels.filter(m => !['anthropic','claude_code','openai','gemini','openrouter'].includes(m.provider_id)).map(m => (
<option key={m.provider_id} value={m.provider_id}>
{m.provider_name} (Tier {m.tier})
</option>
))}
</select>
</div>
)}
<div className="flex-1">
<label className="block text-xs font-medium text-dark-400 mb-1">Model</label>
<select
value={selectedModel}
onChange={e => setSelectedModel(e.target.value)}
disabled={isRunning}
className="w-full px-3 py-2 bg-dark-900 border border-dark-600 rounded-lg text-sm text-white focus:outline-none focus:border-green-500 disabled:opacity-50 transition-colors"
>
<option value="">Auto (default)</option>
{selectedProvider === 'anthropic' || selectedProvider === 'claude_code' || selectedProvider === '' ? (
<>
<option value="claude-opus-4-20250514">Claude Opus 4</option>
<option value="claude-sonnet-4-20250514">Claude Sonnet 4</option>
<option value="claude-sonnet-4-5-20250929">Claude Sonnet 4.5</option>
<option value="claude-haiku-4-5-20251001">Claude Haiku 4.5</option>
</>
) : null}
{(selectedProvider && availableModels.find(m => m.provider_id === selectedProvider)?.available_models || [])
.filter(m => !m.startsWith('claude-'))
.map(model => (
<option key={model} value={model}>{model}</option>
))
}
</select>
</div>
</div>
{/* Multi-target textarea */}
{multiTarget && (
+2 -2
View File
@@ -369,8 +369,8 @@ export default function HomePage() {
{/* ── Quick Actions ─────────────────────────────────────── */}
<div className="grid grid-cols-2 sm:grid-cols-4 gap-3">
{([
{ label: 'Auto Pentest', icon: Zap, to: '/auto', color: 'text-green-400', bg: 'bg-green-500/10 hover:bg-green-500/20', border: 'border-green-500/20 hover:border-green-500/40', desc: '3-stream AI testing' },
{ label: 'Full IA Testing', icon: Shield, to: '/full-ia', color: 'text-red-400', bg: 'bg-red-500/10 hover:bg-red-500/20', border: 'border-red-500/20 hover:border-red-500/40', desc: '100 vuln types' },
{ label: 'Auto Pentest', icon: Zap, to: '/auto', color: 'text-green-400', bg: 'bg-green-500/10 hover:bg-green-500/20', border: 'border-green-500/20 hover:border-green-500/40', desc: '109 agents + 100 vulns' },
{ label: 'AI Agent', icon: Shield, to: '/scan/new', color: 'text-red-400', bg: 'bg-red-500/10 hover:bg-red-500/20', border: 'border-red-500/20 hover:border-red-500/40', desc: 'Custom AI scan' },
{ label: 'Vuln Lab', icon: FlaskConical, to: '/vuln-lab', color: 'text-purple-400', bg: 'bg-purple-500/10 hover:bg-purple-500/20', border: 'border-purple-500/20 hover:border-purple-500/40', desc: 'Per-type challenges' },
{ label: 'Terminal', icon: Terminal, to: '/terminal', color: 'text-cyan-400', bg: 'bg-cyan-500/10 hover:bg-cyan-500/20', border: 'border-cyan-500/20 hover:border-cyan-500/40', desc: 'AI chat + commands' },
] as const).map(action => (
+1 -1
View File
@@ -1,6 +1,6 @@
{
"version": "1.0",
"updated_at": "2026-02-24T13:16:20.190712",
"updated_at": "2026-03-25T01:48:34.034821",
"tasks": [
{
"id": "recon_full",
+148 -641
View File
@@ -1,689 +1,196 @@
#!/usr/bin/env bash
# ============================================================================
# NeuroSploit v3 - Rebuild & Launch Script
# NeuroSploit v3 Rebuild & Launch (Claude 4.6)
# ============================================================================
# Usage: chmod +x rebuild.sh && ./rebuild.sh
# Options:
# --backend-only Only start the backend (skip frontend)
# --frontend-only Only start the frontend (skip backend)
# --build Build frontend for production instead of dev mode
# --install Force reinstall all dependencies
# --reset-db Delete and recreate the database (for schema changes)
# ./rebuild.sh Default (backend + frontend)
# ./rebuild.sh --backend-only Skip frontend
# ./rebuild.sh --frontend-only Skip backend
# ./rebuild.sh --model MODEL Override LLM model
# ./rebuild.sh --install Force reinstall dependencies
# ./rebuild.sh --reset-db Delete + recreate database
# ./rebuild.sh --build Production frontend build
# ./rebuild.sh --port 9000 Custom backend port
# ============================================================================
set -e
PROJECT_DIR="/opt/NeuroSploitv2"
VENV_DIR="$PROJECT_DIR/venv"
FRONTEND_DIR="$PROJECT_DIR/frontend"
DATA_DIR="$PROJECT_DIR/data"
LOGS_DIR="$PROJECT_DIR/logs"
PID_DIR="$PROJECT_DIR/.pids"
DB_PATH="$DATA_DIR/neurosploit.db"
DIR="/opt/NeuroSploitv2"
VENV="$DIR/venv"
FRONT="$DIR/frontend"
LOGS="$DIR/logs"
PIDS="$DIR/.pids"
DB="$DIR/data/neurosploit.db"
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m'
# ── Colors ───────────────────────────────────────────────────────────
R='\033[0;31m' G='\033[0;32m' Y='\033[1;33m' B='\033[0;34m' C='\033[0;36m' N='\033[0m'
header() { echo -e "\n${C}━━━ $1 ━━━${N}"; }
ok() { echo -e " ${G}${N} $1"; }
warn() { echo -e " ${Y}!${N} $1"; }
fail() { echo -e " ${R}${N} $1"; exit 1; }
# Parse args
BACKEND_ONLY=false
FRONTEND_ONLY=false
PRODUCTION_BUILD=false
FORCE_INSTALL=false
RESET_DB=false
# ── Parse args ───────────────────────────────────────────────────────
BACK_ONLY=false; FRONT_ONLY=false; BUILD=false; INSTALL=false; RESET=false
MODEL=""; PORT=8000; FPORT=3000
for arg in "$@"; do
case $arg in
--backend-only) BACKEND_ONLY=true ;;
--frontend-only) FRONTEND_ONLY=true ;;
--build) PRODUCTION_BUILD=true ;;
--install) FORCE_INSTALL=true ;;
--reset-db) RESET_DB=true ;;
while [[ $# -gt 0 ]]; do
case $1 in
--backend-only) BACK_ONLY=true; shift ;;
--frontend-only) FRONT_ONLY=true; shift ;;
--build) BUILD=true; shift ;;
--install) INSTALL=true; shift ;;
--reset-db) RESET=true; shift ;;
--model) MODEL="$2"; shift 2 ;;
--port) PORT="$2"; shift 2 ;;
--frontend-port) FPORT="$2"; shift 2 ;;
*) shift ;;
esac
done
header() {
echo ""
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${CYAN} $1${NC}"
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
}
# ── 0. Stop previous ────────────────────────────────────────────────
header "Stopping previous"
mkdir -p "$PIDS" "$LOGS" "$DIR/data" "$DIR/reports/screenshots"
step() {
echo -e "${GREEN}[+]${NC} $1"
}
warn() {
echo -e "${YELLOW}[!]${NC} $1"
}
fail() {
echo -e "${RED}[x]${NC} $1"
exit 1
}
# ============================================================================
# 0. Kill previous instances
# ============================================================================
header "Stopping previous instances"
mkdir -p "$PID_DIR"
# Kill by PID files if they exist
for pidfile in "$PID_DIR"/*.pid; do
[ -f "$pidfile" ] || continue
pid=$(cat "$pidfile" 2>/dev/null)
if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
step "Stopping process $pid ($(basename "$pidfile" .pid))"
kill "$pid" 2>/dev/null || true
sleep 1
kill -9 "$pid" 2>/dev/null || true
fi
rm -f "$pidfile"
for f in "$PIDS"/*.pid; do
[ -f "$f" ] || continue
pid=$(cat "$f" 2>/dev/null)
[ -n "$pid" ] && kill "$pid" 2>/dev/null && ok "Stopped $(basename "$f" .pid)"
rm -f "$f"
done
# Also kill any lingering uvicorn/vite on our ports
if lsof -ti:8000 >/dev/null 2>&1; then
step "Killing process on port 8000"
kill $(lsof -ti:8000) 2>/dev/null || true
fi
if lsof -ti:3000 >/dev/null 2>&1; then
step "Killing process on port 3000"
kill $(lsof -ti:3000) 2>/dev/null || true
fi
lsof -ti:$PORT >/dev/null 2>&1 && kill $(lsof -ti:$PORT) 2>/dev/null || true
lsof -ti:$FPORT >/dev/null 2>&1 && kill $(lsof -ti:$FPORT) 2>/dev/null || true
sleep 1
step "Previous instances stopped"
# ============================================================================
# 1. Ensure directories exist
# ============================================================================
header "Preparing directories"
mkdir -p "$DATA_DIR" "$LOGS_DIR" "$PID_DIR"
mkdir -p "$PROJECT_DIR/reports/screenshots"
mkdir -p "$PROJECT_DIR/reports/benchmark_results/logs"
mkdir -p "$DATA_DIR/vectorstore"
mkdir -p "$DATA_DIR/checkpoints"
step "Directories ready"
# ── 1. Database reset ───────────────────────────────────────────────
if [ "$RESET" = true ] && [ -f "$DB" ]; then
header "Reset database"
cp "$DB" "$DB.bak.$(date +%s)"
rm -f "$DB"
ok "DB backed up and deleted"
fi
# ============================================================================
# 1b. Database reset (if requested)
# ============================================================================
if [ "$RESET_DB" = true ]; then
header "Resetting database"
if [ -f "$DB_PATH" ]; then
BACKUP="$DB_PATH.backup.$(date +%Y%m%d%H%M%S)"
step "Backing up existing DB to $BACKUP"
cp "$DB_PATH" "$BACKUP"
rm -f "$DB_PATH"
step "Database deleted (will be recreated with new schema on startup)"
# ── 2. Environment check ────────────────────────────────────────────
header "Environment"
[ -f "$DIR/.env" ] || { [ -f "$DIR/.env.example" ] && cp "$DIR/.env.example" "$DIR/.env" && warn "Created .env from example"; } || fail "No .env"
ok ".env"
PY=$(command -v python3 || command -v python) || fail "Python not found"
ok "Python: $($PY --version 2>&1)"
if [ "$BACK_ONLY" = false ]; then
command -v node &>/dev/null || fail "Node.js not found"
ok "Node: $(node --version)"
fi
command -v docker &>/dev/null && ok "Docker: available" || warn "Docker: not found (sandbox disabled)"
# ── 3. Backend setup ────────────────────────────────────────────────
if [ "$FRONT_ONLY" = false ]; then
header "Backend"
[ -d "$VENV" ] && [ "$INSTALL" = false ] || { $PY -m venv "$VENV"; ok "Venv created"; }
source "$VENV/bin/activate"
if [ "$INSTALL" = true ] || [ ! -f "$VENV/.ok" ]; then
pip install -q --upgrade pip
pip install -q -r "$DIR/backend/requirements.txt" 2>&1 | tail -3
pip install -q -r "$DIR/requirements.txt" 2>&1 | tail -3
[ -f "$DIR/requirements-optional.txt" ] && pip install -q -r "$DIR/requirements-optional.txt" 2>/dev/null || true
touch "$VENV/.ok"
ok "Dependencies installed"
else
step "No existing database found"
fi
fi
# ============================================================================
# 2. Environment check
# ============================================================================
header "Checking environment"
if [ ! -f "$PROJECT_DIR/.env" ]; then
if [ -f "$PROJECT_DIR/.env.example" ]; then
warn ".env not found, copying from .env.example"
cp "$PROJECT_DIR/.env.example" "$PROJECT_DIR/.env"
else
fail ".env file not found and no .env.example to copy from"
fi
fi
step ".env file present"
# Check Python
if command -v python3 &>/dev/null; then
PYTHON=python3
elif command -v python &>/dev/null; then
PYTHON=python
else
fail "Python not found. Install Python 3.10+"
fi
step "Python: $($PYTHON --version)"
# Check Node
if command -v node &>/dev/null; then
step "Node: $(node --version)"
else
if [ "$BACKEND_ONLY" = false ]; then
fail "Node.js not found. Install Node.js 18+"
fi
fi
# Check Docker (optional - needed for sandbox & benchmarks)
if command -v docker &>/dev/null; then
step "Docker: $(docker --version 2>/dev/null | head -1)"
# Check compose
if docker compose version &>/dev/null 2>&1; then
step "Docker Compose: plugin (docker compose)"
elif command -v docker-compose &>/dev/null; then
step "Docker Compose: standalone ($(docker-compose version --short 2>/dev/null))"
else
warn "Docker Compose not found (needed for sandbox & benchmarks)"
fi
else
warn "Docker not found (optional - needed for sandbox & benchmarks)"
fi
# ============================================================================
# 3. Python virtual environment & dependencies
# ============================================================================
if [ "$FRONTEND_ONLY" = false ]; then
header "Setting up Python backend"
if [ ! -d "$VENV_DIR" ] || [ "$FORCE_INSTALL" = true ]; then
step "Creating virtual environment..."
$PYTHON -m venv "$VENV_DIR"
ok "Dependencies cached"
fi
source "$VENV_DIR/bin/activate"
step "Virtual environment activated"
if [ "$FORCE_INSTALL" = true ] || [ ! -f "$VENV_DIR/.deps_installed" ]; then
step "Installing backend dependencies..."
pip install --quiet --upgrade pip
# Install from requirements files (pyproject.toml is for tool config only)
pip install --quiet -r "$PROJECT_DIR/backend/requirements.txt" 2>&1 | tail -5
pip install --quiet -r "$PROJECT_DIR/requirements.txt" 2>&1 | tail -5
touch "$VENV_DIR/.deps_installed"
step "Core dependencies installed"
# Try optional deps (may fail on Python <3.10)
if [ -f "$PROJECT_DIR/requirements-optional.txt" ]; then
step "Installing optional dependencies (best-effort)..."
pip install --quiet -r "$PROJECT_DIR/requirements-optional.txt" 2>/dev/null && \
step "Optional deps installed (mcp, playwright)" || \
warn "Some optional deps skipped (Python 3.10+ required for mcp/playwright)"
fi
else
step "Dependencies already installed (use --install to force)"
fi
# Validate key modules
step "Validating Python modules..."
$PYTHON -c "
import sys
# === Core Platform (14) ===
core_modules = [
('backend.main', 'FastAPI App'),
('backend.config', 'Settings'),
('core.llm_manager', 'LLM Manager'),
('core.model_router', 'Model Router'),
('core.scheduler', 'Scheduler'),
('core.knowledge_augmentor', 'Knowledge Augmentor'),
('core.browser_validator', 'Browser Validator'),
('core.mcp_client', 'MCP Client'),
('core.mcp_server', 'MCP Server'),
('core.sandbox_manager', 'Sandbox Manager'),
('core.context_builder', 'Context Builder'),
('core.pentest_executor', 'Pentest Executor'),
('core.tool_installer', 'Tool Installer'),
('core.report_generator', 'Report Generator (CLI)'),
]
# === API Layer (18) ===
api_modules = [
('backend.api.v1.agent', 'Agent API'),
('backend.api.v1.scans', 'Scans API'),
('backend.api.v1.targets', 'Targets API'),
('backend.api.v1.prompts', 'Prompts API'),
('backend.api.v1.reports', 'Reports API'),
('backend.api.v1.dashboard', 'Dashboard API'),
('backend.api.v1.vulnerabilities', 'Vulnerabilities API'),
('backend.api.v1.settings', 'Settings API'),
('backend.api.v1.agent_tasks', 'Agent Tasks API'),
('backend.api.v1.scheduler', 'Scheduler API'),
('backend.api.v1.vuln_lab', 'VulnLab API'),
('backend.api.v1.terminal', 'Terminal API'),
('backend.api.v1.sandbox', 'Sandbox API'),
('backend.api.v1.knowledge', 'Knowledge API'),
('backend.api.v1.mcp', 'MCP API'),
('backend.api.v1.providers', 'Providers API'),
('backend.api.v1.full_ia', 'Full IA Testing API'),
('backend.api.v1.cli_agent', 'CLI Agent API'),
]
# === VulnEngine (18) ===
vuln_modules = [
('backend.core.vuln_engine.engine', 'VulnEngine Core'),
('backend.core.vuln_engine.registry', 'VulnEngine Registry'),
('backend.core.vuln_engine.payload_generator', 'VulnEngine Payloads'),
('backend.core.vuln_engine.ai_prompts', 'VulnEngine AI Prompts'),
('backend.core.vuln_engine.pentest_playbook', 'VulnEngine Playbook'),
('backend.core.vuln_engine.system_prompts', 'Anti-Hallucination Prompts'),
('backend.core.vuln_engine.testers.injection', 'Tester: Injection'),
('backend.core.vuln_engine.testers.auth', 'Tester: Auth'),
('backend.core.vuln_engine.testers.authorization', 'Tester: Authorization'),
('backend.core.vuln_engine.testers.client_side', 'Tester: Client-Side'),
('backend.core.vuln_engine.testers.file_access', 'Tester: File Access'),
('backend.core.vuln_engine.testers.infrastructure', 'Tester: Infrastructure'),
('backend.core.vuln_engine.testers.request_forgery', 'Tester: Request Forgery'),
('backend.core.vuln_engine.testers.advanced_injection', 'Tester: Advanced Injection'),
('backend.core.vuln_engine.testers.logic', 'Tester: Logic'),
('backend.core.vuln_engine.testers.data_exposure', 'Tester: Data Exposure'),
('backend.core.vuln_engine.testers.cloud_supply', 'Tester: Cloud/Supply Chain'),
('backend.core.vuln_engine.testers.base_tester', 'Tester: Base Class'),
]
# === Agent Core (14) ===
agent_modules = [
('backend.core.autonomous_agent', 'Autonomous Agent'),
('backend.core.agent_memory', 'Agent Memory'),
('backend.core.response_verifier', 'Response Verifier'),
('backend.core.task_library', 'Task Library'),
('backend.core.execution_history', 'Execution History'),
('backend.core.methodology_loader', 'Methodology Loader'),
('backend.core.ai_pentest_agent', 'AI Pentest Agent'),
('backend.core.ai_prompt_processor', 'AI Prompt Processor'),
('backend.core.autonomous_scanner', 'Autonomous Scanner'),
('backend.core.recon_integration', 'Recon Integration'),
('backend.core.report_generator', 'Report Generator (Backend)'),
('backend.core.tool_executor', 'Tool Executor'),
('backend.core.prompt_engine.parser', 'Prompt Engine Parser'),
('backend.core.report_engine.generator', 'Report Engine Generator'),
]
# === Validation Pipeline (6) ===
validation_modules = [
('backend.core.negative_control', 'Negative Control Engine'),
('backend.core.proof_of_execution', 'Proof of Execution'),
('backend.core.confidence_scorer', 'Confidence Scorer'),
('backend.core.validation_judge', 'Validation Judge'),
('backend.core.access_control_learner', 'Access Control Learner'),
('backend.core.adaptive_learner', 'Adaptive Learner'),
]
# === Agent Autonomy (5) ===
autonomy_modules = [
('backend.core.request_engine', 'Request Engine'),
('backend.core.waf_detector', 'WAF Detector'),
('backend.core.strategy_adapter', 'Strategy Adapter'),
('backend.core.chain_engine', 'Chain Engine'),
('backend.core.auth_manager', 'Auth Manager'),
]
# === AI Reasoning & Intelligence (8) ===
intelligence_modules = [
('backend.core.token_budget', 'Token Budget'),
('backend.core.reasoning_engine', 'Reasoning Engine'),
('backend.core.agent_tasks', 'Agent Tasks'),
('backend.core.endpoint_classifier', 'Endpoint Classifier'),
('backend.core.cve_hunter', 'CVE Hunter'),
('backend.core.deep_recon', 'Deep Recon'),
('backend.core.banner_analyzer', 'Banner Analyzer'),
('backend.core.param_analyzer', 'Param Analyzer'),
]
# === Testing & Exploitation (8) ===
testing_modules = [
('backend.core.payload_mutator', 'Payload Mutator'),
('backend.core.xss_context_analyzer', 'XSS Context Analyzer'),
('backend.core.xss_validator', 'XSS Validator'),
('backend.core.poc_generator', 'PoC Generator'),
('backend.core.exploit_generator', 'Exploit Generator'),
('backend.core.poc_validator', 'PoC Validator'),
('backend.core.request_repeater', 'Request Repeater'),
('backend.core.site_analyzer', 'Site Analyzer'),
]
# === Multi-Agent & Orchestration (9) ===
multiagent_modules = [
('backend.core.agent_base', 'Specialist Agent Base'),
('backend.core.specialist_agents', 'Specialist Agents'),
('backend.core.agent_orchestrator', 'Agent Orchestrator'),
('backend.core.researcher_agent', 'Researcher AI Agent'),
('backend.core.vuln_orchestrator', 'Vuln Orchestrator'),
('backend.core.vuln_type_agent', 'Vuln Type Agent'),
('backend.core.cli_agent_runner', 'CLI Agent Runner'),
('backend.core.cli_output_parser', 'CLI Output Parser'),
('backend.core.cli_instructions_builder', 'CLI Instructions Builder'),
]
# === RAG System (5) ===
rag_modules = [
('backend.core.rag.engine', 'RAG Engine'),
('backend.core.rag.vectorstore', 'RAG VectorStore'),
('backend.core.rag.few_shot', 'RAG Few-Shot'),
('backend.core.rag.reasoning_templates', 'RAG Reasoning Templates'),
('backend.core.rag.reasoning_memory', 'RAG Reasoning Memory'),
]
# === Smart Router (5) ===
router_modules = [
('backend.core.smart_router', 'Smart Router Package'),
('backend.core.smart_router.provider_registry', 'Provider Registry'),
('backend.core.smart_router.router', 'Router Core'),
('backend.core.smart_router.token_extractor', 'Token Extractor'),
('backend.core.smart_router.token_refresher', 'Token Refresher'),
]
# === Kali Sandbox (3) ===
kali_modules = [
('core.tool_registry', 'Tool Registry (56 tools)'),
('core.kali_sandbox', 'Kali Sandbox'),
('core.container_pool', 'Container Pool'),
]
# === Operations (3) ===
operations_modules = [
('backend.core.checkpoint_manager', 'Checkpoint Manager'),
('backend.core.notification_manager', 'Notification Manager'),
('backend.core.knowledge_processor', 'Knowledge Processor'),
]
all_groups = [
('Core Platform', core_modules),
('API Layer', api_modules),
('VulnEngine', vuln_modules),
('Agent Core', agent_modules),
('Validation Pipeline', validation_modules),
('Agent Autonomy', autonomy_modules),
('AI Reasoning & Intelligence', intelligence_modules),
('Testing & Exploitation', testing_modules),
('Multi-Agent & Orchestration', multiagent_modules),
('RAG System', rag_modules),
('Smart Router', router_modules),
('Kali Sandbox', kali_modules),
('Operations', operations_modules),
]
total = 0
errors = 0
for group_name, modules in all_groups:
print(f' --- {group_name} ---')
for mod, name in modules:
total += 1
try:
__import__(mod)
print(f' OK {name}')
except Exception as e:
err_short = str(e).split(chr(10))[0][:80]
print(f' WARN {name}: {err_short}')
errors += 1
print(f'\n {total - errors}/{total} modules loaded ({errors} warnings)')
" 2>&1 || true
# Validate knowledge base
step "Validating knowledge base..."
$PYTHON -c "
import json, os
kb_path = os.path.join('$PROJECT_DIR', 'data', 'vuln_knowledge_base.json')
if os.path.exists(kb_path):
kb = json.load(open(kb_path))
types = len(kb.get('vulnerability_types', {}))
insights = len(kb.get('xbow_insights', kb.get('attack_insights', {})))
print(f' OK Knowledge base: {types} vuln types, {insights} insight categories')
else:
print(' WARN Knowledge base not found at data/vuln_knowledge_base.json')
" 2>&1 || true
# Validate VulnEngine coverage
step "Validating VulnEngine coverage..."
$PYTHON -c "
from backend.core.vuln_engine.registry import VulnerabilityRegistry
from backend.core.vuln_engine.payload_generator import PayloadGenerator
from backend.core.vuln_engine.ai_prompts import VULN_AI_PROMPTS
from backend.core.vuln_engine.pentest_playbook import PENTEST_PLAYBOOK, get_testing_prompts
from backend.core.vuln_engine.system_prompts import CONTEXT_PROMPTS, VULN_TYPE_PROOF_REQUIREMENTS
r = VulnerabilityRegistry()
p = PayloadGenerator()
total_payloads = sum(len(v) for v in p.payload_libraries.values())
total_prompts = sum(len(get_testing_prompts(v)) for v in PENTEST_PLAYBOOK)
# Count AI prompt builder functions (deep test + stream prompts)
import inspect, backend.core.vuln_engine.ai_prompts as ap
prompt_funcs = [n for n, f in inspect.getmembers(ap, inspect.isfunction) if n.startswith('get_')]
print(f' OK Registry: {len(r.VULNERABILITY_INFO)} types, {len(r.TESTER_CLASSES)} testers')
print(f' OK Payloads: {total_payloads} across {len(p.payload_libraries)} categories')
print(f' OK AI Prompts: {len(VULN_AI_PROMPTS)} per-vuln + {len(prompt_funcs)} builder functions')
print(f' OK Playbook: {len(PENTEST_PLAYBOOK)} vuln types, {total_prompts} testing prompts')
print(f' OK System Prompts: {len(CONTEXT_PROMPTS)} contexts, {len(VULN_TYPE_PROOF_REQUIREMENTS)} proof reqs')
" 2>&1 || true
# Validate RAG system
step "Validating RAG system..."
$PYTHON -c "
from backend.core.rag.reasoning_templates import REASONING_TEMPLATES
from backend.core.rag.few_shot import FewShotSelector
fs = FewShotSelector()
curated = getattr(fs, '_curated_examples', {})
total_ex = sum(len(ex) for cat in curated.values() if isinstance(cat, dict) for ex in cat.values() if isinstance(ex, list))
print(f' OK Reasoning Templates: {len(REASONING_TEMPLATES)} vuln types')
print(f' OK Few-Shot Examples: {len(curated)} categories, {total_ex} curated TP/FP examples')
# Quick validation
$PY -c "
import sys; sys.path.insert(0,'$DIR')
mods = ['backend.main','backend.config','backend.core.autonomous_agent','backend.core.md_agent',
'backend.core.smart_router.router','backend.core.vuln_engine.registry']
ok=err=0
for m in mods:
try: __import__(m); ok+=1
except: err+=1
print(f' {ok}/{ok+err} core modules OK')
" 2>&1 || true
fi
# ============================================================================
# 4. Frontend dependencies
# ============================================================================
if [ "$BACKEND_ONLY" = false ]; then
header "Setting up React frontend"
cd "$FRONTEND_DIR"
if [ ! -d "node_modules" ] || [ "$FORCE_INSTALL" = true ]; then
step "Installing frontend dependencies..."
# ── 4. Frontend setup ───────────────────────────────────────────────
if [ "$BACK_ONLY" = false ]; then
header "Frontend"
cd "$FRONT"
if [ ! -d "node_modules" ] || [ "$INSTALL" = true ]; then
npm install --silent 2>&1 | tail -3
step "Frontend dependencies installed"
ok "Dependencies installed"
else
step "node_modules present (use --install to force)"
ok "Dependencies cached"
fi
cd "$PROJECT_DIR"
cd "$DIR"
fi
# ============================================================================
# 5. Launch backend
# ============================================================================
if [ "$FRONTEND_ONLY" = false ]; then
header "Starting FastAPI backend (port 8000)"
# ── 5. Launch backend ───────────────────────────────────────────────
if [ "$FRONT_ONLY" = false ]; then
header "Starting backend :$PORT"
source "$VENV/bin/activate"
set -a; source "$DIR/.env"; set +a
source "$VENV_DIR/bin/activate"
[ -n "$MODEL" ] && export DEFAULT_LLM_MODEL="$MODEL" && ok "Model: $MODEL"
# Export env vars
set -a
source "$PROJECT_DIR/.env"
set +a
PYTHONPATH="$DIR" uvicorn backend.main:app \
--host 0.0.0.0 --port $PORT --reload --log-level info \
> "$LOGS/backend.log" 2>&1 &
echo $! > "$PIDS/backend.pid"
ok "PID: $(cat "$PIDS/backend.pid")"
PYTHONPATH="$PROJECT_DIR" uvicorn backend.main:app \
--host 0.0.0.0 \
--port 8000 \
--reload \
--log-level info \
> "$LOGS_DIR/backend.log" 2>&1 &
BACKEND_PID=$!
echo "$BACKEND_PID" > "$PID_DIR/backend.pid"
step "Backend started (PID: $BACKEND_PID)"
step "Backend logs: $LOGS_DIR/backend.log"
# Wait for backend to be ready
step "Waiting for backend..."
for i in $(seq 1 15); do
if curl -s http://localhost:8000/docs >/dev/null 2>&1; then
step "Backend is ready"
break
fi
if [ $i -eq 15 ]; then
warn "Backend may still be starting. Check logs."
fi
curl -s "http://localhost:$PORT/docs" >/dev/null 2>&1 && break
sleep 1
done
fi
# ============================================================================
# 6. Launch frontend
# ============================================================================
if [ "$BACKEND_ONLY" = false ]; then
header "Starting React frontend (port 3000)"
cd "$FRONTEND_DIR"
if [ "$PRODUCTION_BUILD" = true ]; then
step "Building production frontend..."
npm run build 2>&1 | tail -5
step "Build complete. Serving from dist/"
npx vite preview --port 3000 \
> "$LOGS_DIR/frontend.log" 2>&1 &
# ── 6. Launch frontend ──────────────────────────────────────────────
if [ "$BACK_ONLY" = false ]; then
header "Starting frontend :$FPORT"
cd "$FRONT"
if [ "$BUILD" = true ]; then
npm run build 2>&1 | tail -3
npx vite preview --port $FPORT > "$LOGS/frontend.log" 2>&1 &
else
step "Starting development server..."
npx vite --port 3000 \
> "$LOGS_DIR/frontend.log" 2>&1 &
npx vite --port $FPORT > "$LOGS/frontend.log" 2>&1 &
fi
FRONTEND_PID=$!
echo "$FRONTEND_PID" > "$PID_DIR/frontend.pid"
step "Frontend started (PID: $FRONTEND_PID)"
step "Frontend logs: $LOGS_DIR/frontend.log"
cd "$PROJECT_DIR"
# Wait for frontend
for i in $(seq 1 10); do
if curl -s http://localhost:3000 >/dev/null 2>&1; then
break
fi
sleep 1
done
echo $! > "$PIDS/frontend.pid"
ok "PID: $(cat "$PIDS/frontend.pid")"
cd "$DIR"
fi
# ============================================================================
# 7. Summary
# ============================================================================
header "NeuroSploit v3 is running"
# ── 7. Summary ──────────────────────────────────────────────────────
echo ""
if [ "$FRONTEND_ONLY" = false ]; then
echo -e " ${GREEN}Backend API:${NC} http://localhost:8000"
echo -e " ${GREEN}API Docs:${NC} http://localhost:8000/docs"
echo -e " ${GREEN}Scheduler API:${NC} http://localhost:8000/api/v1/scheduler/"
echo -e " ${GREEN}VulnLab API:${NC} http://localhost:8000/api/v1/vuln-lab/"
fi
if [ "$BACKEND_ONLY" = false ]; then
echo -e " ${GREEN}Frontend UI:${NC} http://localhost:3000"
fi
echo -e "${C}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${N}"
echo -e "${G} NeuroSploit v3 — Agent-First AI Pentest Platform${N}"
echo -e "${C}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${N}"
echo ""
echo -e " ${BLUE}Logs:${NC}"
[ "$FRONTEND_ONLY" = false ] && echo -e " Backend: tail -f $LOGS_DIR/backend.log"
[ "$BACKEND_ONLY" = false ] && echo -e " Frontend: tail -f $LOGS_DIR/frontend.log"
[ "$FRONT_ONLY" = false ] && {
echo -e " ${G}API${N} http://localhost:$PORT"
echo -e " ${G}Docs${N} http://localhost:$PORT/docs"
echo -e " ${G}Model${N} ${MODEL:-claude-sonnet-4-6-20250918}"
}
[ "$BACK_ONLY" = false ] && echo -e " ${G}Frontend${N} http://localhost:$FPORT"
echo ""
echo -e " ${YELLOW}Stop:${NC} $0 (re-run kills previous)"
echo -e " kill \$(cat $PID_DIR/backend.pid) \$(cat $PID_DIR/frontend.pid)"
echo -e " ${B}Architecture${N}"
echo -e " ├─ 108 AI agents (real HTTP testing, PLAN→EXECUTE→ANALYZE)"
echo -e " ├─ 100 vulnerability types + validation pipeline"
echo -e " ├─ Claude 4.6: Opus, Sonnet 4.6, Sonnet 4.5, Haiku 4.5"
echo -e " ├─ 20 LLM providers (auto-failover)"
echo -e " └─ Agent-first flow: Recon (20%) → Agent Grid (65%) → Report (15%)"
echo ""
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${GREEN} NeuroSploit v3 - Autonomous AI Penetration Testing Platform${NC}"
echo -e "${GREEN} 116 modules | 100 vuln types | 18 API routes | 18 frontend pages${NC}"
echo -e ""
echo -e " ${BLUE}VulnEngine (100-Type):${NC}"
echo -e " - Registry: 100 vuln types, 526+ payloads, 100 testers"
echo -e " - AI Prompts: 100 per-vuln decision prompts + pentest playbook"
echo -e " - System Prompts: 12 anti-hallucination composable prompts"
echo -e " - Methodology: Deep injection from .md methodology files"
echo -e " - Knowledge Base: 100 vuln types + RAG-indexed insights"
echo -e ""
echo -e " ${BLUE}Autonomous Agent (AI-Powered Pentester):${NC}"
echo -e " - Auto Pentest: 3 AI-parallel streams (recon + junior + tools)"
echo -e " - AI Master Plan: Pre-stream strategic planning (target profiling)"
echo -e " - AI Deep Test: Iterative OBSERVE->PLAN->EXECUTE->ANALYZE->ADAPT"
echo -e " - AI Recon Analysis: Endpoint prioritization, hidden surface probing"
echo -e " - AI Payload Gen: Context-aware payloads per endpoint x vuln_type"
echo -e " - AI Tool Analysis: Tool output analysis for real findings vs noise"
echo -e " - Full IA Testing: Methodology-driven comprehensive sessions"
echo -e " - Multi-Session: Up to 5 concurrent scans"
echo -e " - Pause/Resume/Stop: Real-time scan control with fast cancel"
echo -e " - Checkpoint Manager: Crash-resilient scan state save/restore"
echo -e " - Recon Integration: 40+ tools (subfinder, amass, nuclei, ffuf)"
echo -e " - WAF Detection: 16 signatures, 12 bypass techniques"
echo -e " - Strategy Adapter: Dead endpoints, diminishing returns, recompute"
echo -e " - Chain Engine: 10 chain rules, exploit chaining, attack graph"
echo -e " - Auth Manager: Multi-user, login form detection, session mgmt"
echo -e " - Request Engine: Retry, rate limit, circuit breaker, adaptive"
echo -e " - Request Repeater: Burp-like send/compare/replay/validate"
echo -e " - Site Analyzer: BFS crawl, JS sink detection, AI architecture"
echo -e ""
echo -e " ${BLUE}Validation Pipeline (Anti-FP):${NC}"
echo -e " - Negative Controls: Benign/empty/no-param baseline comparison"
echo -e " - Proof of Execution: 25+ per-vuln-type proof methods"
echo -e " - Confidence Scorer: Numeric 0-100 with breakdown"
echo -e " - Validation Judge: Sole authority (controls+proof+AI+score)"
echo -e " - Access Control: Adaptive TP/FP learning, 9 patterns"
echo -e " - Adaptive Learner: Cross-scan TP/FP learning (100 vuln types)"
echo -e ""
echo -e " ${BLUE}AI Reasoning & Intelligence:${NC}"
echo -e " - ReACT Engine: Think/plan/reflect reasoning loop"
echo -e " - Token Budget: Budget tracking with graceful degradation"
echo -e " - Endpoint Classifier: 8 types with risk scoring"
echo -e " - CVE Hunter: NVD API + GitHub exploit search"
echo -e " - Deep Recon: JS crawling, sitemap, robots, API enum"
echo -e " - Banner Analyzer: 80 known CVEs, 19 EOL versions"
echo -e " - Param Analyzer: 8 semantic categories, risk ranking"
echo -e ""
echo -e " ${BLUE}Testing & Exploitation:${NC}"
echo -e " - Payload Mutator: 14 mutation strategies, failure analysis"
echo -e " - XSS Validator: Playwright popup/cookie/DOM/event/CSP"
echo -e " - XSS Context: 8 context checks (attribute, script, etc.)"
echo -e " - Exploit Generator: AI-enhanced PoC, zero-day hypothesis"
echo -e " - PoC Validator: HTTP replay, per-vuln markers, static analysis"
echo -e " - PoC Generator: 20+ per-type exploit code generators"
echo -e ""
echo -e " ${BLUE}Multi-Agent & Orchestration:${NC}"
echo -e " - 5 Specialists: Recon, Exploit, Validator, CVEHunter, Report"
echo -e " - Orchestrator: 3-phase pipeline coordinator with handoffs"
echo -e " - Researcher AI: Hypothesis-driven 0-day discovery with Kali"
echo -e " - Vuln Orchestrator: Per-vuln-type parallel agent orchestration"
echo -e " - Vuln Type Agents: Specialist agents per vulnerability type"
echo -e ""
echo -e " ${BLUE}CLI Agent (AI CLI inside Kali):${NC}"
echo -e " - 3 Providers: Claude Code, Gemini CLI, Codex CLI"
echo -e " - Standalone Mode: CLI Agent runs full pentest autonomously"
echo -e " - Auto Pentest Phase: Optional CLI agent phase in auto pentest"
echo -e " - 3-Tier Parsing: JSON markers + regex + AI extraction"
echo -e " - OAuth Integration: SmartRouter token injection into container"
echo -e ""
echo -e " ${BLUE}RAG System:${NC}"
echo -e " - VectorStore: BM25/TF-IDF/ChromaDB backends"
echo -e " - Few-Shot: Curated TP/FP examples for 15+ vuln types"
echo -e " - Reasoning Templates: Structured CoT for 18 vuln types"
echo -e " - Reasoning Memory: Cross-scan pseudo-fine-tuning"
echo -e ""
echo -e " ${BLUE}Smart Router (20 Providers):${NC}"
echo -e " - 8 CLI OAuth: Claude, Gemini, Copilot, Cursor, etc."
echo -e " - 11 API Providers: Anthropic, OpenAI, Google, OpenRouter, etc."
echo -e " - Tier Failover: Auto round-robin with quota tracking"
echo -e " - Token Refresh: Auto CLI token re-extraction + OAuth refresh"
echo -e ""
echo -e " ${BLUE}Kali Sandbox (Container-Per-Scan):${NC}"
echo -e " - Tool Registry: 56 tools (16 pre-installed + 40 on-demand)"
echo -e " - Container Pool: Max concurrent, TTL, orphan cleanup"
echo -e " - VPN Support: OpenVPN/WireGuard per-container tunnels"
echo -e " - Researcher AI: AI-driven tool selection and execution"
echo -e ""
echo -e " ${BLUE}Platform & Operations:${NC}"
echo -e " - 18 API Routes: Agent, Scans, VulnLab, Terminal, Full IA, etc."
echo -e " - 18 Frontend Pages: Auto Pentest, VulnLab, Terminal, Dashboard, etc."
echo -e " - Terminal Agent: AI chat + Kali sandbox + VPN integration"
echo -e " - Vuln Lab: 100 types, PortSwigger/CTF/custom targets"
echo -e " - Knowledge Manager: Upload/index custom security documents"
echo -e " - Notifications: Discord, Telegram, WhatsApp/Twilio alerts"
echo -e " - Scheduler: Cron & interval scheduling"
echo -e " - Benchmark: 104 CTF challenges for accuracy testing"
echo -e " - AI Reports: Dual HTML+JSON with per-finding AI analysis"
echo -e " - MCP Server: 12 tools (screenshot, dns, port scan, etc.)"
echo -e " - Reset DB: ./rebuild.sh --reset-db (schema changes)"
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e " ${B}Auto Pentest Flow${N}"
echo -e " 0-20% Recon: endpoints, tech stack, WAF, params, CVEs"
echo -e " 20-85% Agent Grid: 108 agents execute real HTTP tests"
echo -e " 85-100% Finalization: chains, screenshots, AI report"
echo ""
echo -e " ${Y}Logs${N} tail -f $LOGS/backend.log"
echo -e " ${Y}Stop${N} kill \$(cat $PIDS/backend.pid $PIDS/frontend.pid 2>/dev/null)"
echo -e "${C}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${N}"
echo ""
# Keep script running so bg processes stay alive
wait