mirror of
https://github.com/CyberSecurityUP/NeuroSploit.git
synced 2026-05-25 15:47:48 +02:00
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:
-12
@@ -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
@@ -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),
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
@@ -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
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) ===
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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:
|
||||
|
||||
@@ -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 />} />
|
||||
|
||||
@@ -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' },
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -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 && (
|
||||
|
||||
@@ -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,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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user