NeuroSploit v3.2.3 - Multi-Agent Security Testing Framework

- Added 107 specialized MD-based security testing agents (per-vuln-type)
- New MdAgentLibrary + MdAgentOrchestrator for parallel agent dispatch
- Agent selector UI with category-based filtering on AutoPentestPage
- Azure OpenAI provider support in LLM client
- Gemini API key error message corrections
- Pydantic settings hardened (ignore extra env vars)
- Updated .gitignore for runtime data artifacts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
CyberSecurityUP
2026-03-16 18:59:22 -03:00
parent e5857d00c1
commit 7563260b2b
119 changed files with 6740 additions and 8 deletions
+123 -3
View File
@@ -4,7 +4,7 @@ import {
Rocket, Shield, ChevronDown, ChevronUp, Loader2,
AlertTriangle, CheckCircle2, Globe, Lock, Bug, MessageSquare,
FileText, ScrollText, X, ExternalLink, Download, Sparkles, Trash2,
Brain, Wrench, Layers, Clock, Search, Activity, Terminal
Brain, Wrench, Layers, Clock, Search, Activity, Terminal, Crosshair
} from 'lucide-react'
import { PieChart, Pie, Cell, Tooltip as RechartsTooltip, ResponsiveContainer } from 'recharts'
import { agentApi, reportsApi, promptsApi, cliAgentApi } from '../services/api'
@@ -115,6 +115,7 @@ function logMessageColor(message: string): string {
if (message.startsWith('[WAF]')) return 'text-amber-400'
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'
return ''
}
@@ -424,8 +425,13 @@ export default function AutoPentestPage() {
const [selectedProvider, setSelectedProvider] = useState('')
const [selectedModel, setSelectedModel] = useState('')
// MD Agent selection
const [availableMdAgents, setAvailableMdAgents] = useState<Array<{ name: string; display_name: string; category: string }>>([])
const [selectedMdAgents, setSelectedMdAgents] = useState<string[]>([])
const [showAgentSelector, setShowAgentSelector] = useState(false)
// CLI Agent mode
const [testMode, setTestMode] = useState<'auto_pentest' | 'cli_agent'>('auto_pentest')
const [testMode, setTestMode] = useState<'auto_pentest' | 'cli_agent' | 'full_llm_pentest'>('auto_pentest')
const [cliProviders, setCliProviders] = useState<Array<{ id: string; name: string; connected: boolean; account_label?: string; source?: string }>>([])
const [cliEnabled, setCliEnabled] = useState(false)
const [selectedCliProvider, setSelectedCliProvider] = useState('')
@@ -433,6 +439,9 @@ export default function AutoPentestPage() {
const [selectedMethodology, setSelectedMethodology] = useState('')
const [enableCliPhase, setEnableCliPhase] = useState(false) // Checkbox in auto_pentest mode
// Learning stats (TP/FP per vuln type)
const [learningStats, setLearningStats] = useState<Record<string, { tp: number; fp: number }>>({})
// History
const [showHistory, setShowHistory] = useState(false)
const [history, setHistory] = useState<Array<any>>([])
@@ -547,6 +556,26 @@ export default function AutoPentestPage() {
.then(data => setAvailableModels(data.models || []))
.catch(() => {})
// Fetch available MD agents
fetch('/api/v1/agent/md-agents')
.then(r => r.json())
.then(data => setAvailableMdAgents(data.agents || []))
.catch(() => {})
// Fetch learning stats (TP/FP counts per vuln type)
fetch('/api/v1/scans/vulnerabilities/learning/stats')
.then(r => r.json())
.then(data => {
if (data.vuln_types) {
const stats: Record<string, { tp: number; fp: number }> = {}
for (const [vt, info] of Object.entries(data.vuln_types as Record<string, any>)) {
stats[vt] = { tp: info.true_positives || 0, fp: info.false_positives || 0 }
}
setLearningStats(stats)
}
})
.catch(() => {})
// Fetch CLI agent providers and methodologies
cliAgentApi.getProviders()
.then(data => {
@@ -776,7 +805,7 @@ export default function AutoPentestPage() {
const isCliMode = testMode === 'cli_agent'
const resp = await agentApi.autoPentest(primaryTarget, {
mode: isCliMode ? 'cli_agent' : 'auto_pentest',
mode: testMode,
subdomain_discovery: subdomainDiscovery,
targets: targetList,
auth_type: authType || undefined,
@@ -789,6 +818,7 @@ export default function AutoPentestPage() {
enable_cli_agent: isCliMode || enableCliPhase || undefined,
cli_agent_provider: (isCliMode || enableCliPhase) ? (selectedCliProvider || undefined) : undefined,
methodology_file: (isCliMode || enableCliPhase) ? (selectedMethodology || undefined) : undefined,
selected_md_agents: selectedMdAgents.length > 0 ? selectedMdAgents : undefined,
})
const newSession: SavedSession = {
@@ -1118,6 +1148,19 @@ export default function AutoPentestPage() {
CLI Agent
{!cliEnabled && <span className="ml-1 text-xs text-dark-500">(disabled)</span>}
</button>
<button
onClick={() => setTestMode('full_llm_pentest')}
disabled={isRunning}
className={`px-4 py-2 rounded-md text-sm font-medium transition-all ${
testMode === 'full_llm_pentest'
? 'bg-red-600 text-white shadow-lg'
: 'text-dark-400 hover:text-white hover:bg-dark-700'
} disabled:opacity-50`}
title="Full AI-driven pentest — LLM plans and executes every test"
>
<Crosshair className="w-4 h-4 inline mr-1.5" />
Full LLM Pentest
</button>
</div>
{/* CLI Agent Options (shown in CLI mode) */}
@@ -1255,6 +1298,83 @@ export default function AutoPentestPage() {
</div>
)}
{/* MD Agent Selection */}
{availableMdAgents.length > 0 && (
<div className="mb-6">
<button
type="button"
onClick={() => setShowAgentSelector(!showAgentSelector)}
className="flex items-center gap-2 text-sm text-dark-300 hover:text-white transition-colors mb-2"
>
{showAgentSelector ? <ChevronUp className="w-4 h-4" /> : <ChevronDown className="w-4 h-4" />}
<Brain className="w-4 h-4" />
AI Agents ({selectedMdAgents.length > 0 ? `${selectedMdAgents.length} selected` : `All ${availableMdAgents.length} agents`})
</button>
{showAgentSelector && (
<div className="p-3 bg-dark-900/50 border border-cyan-500/20 rounded-lg">
<p className="text-xs text-dark-400 mb-2">
Select which AI agents run after recon. Empty = all {availableMdAgents.length} offensive agents.
</p>
<div className="grid grid-cols-2 sm:grid-cols-3 gap-2">
{availableMdAgents.map(agent => {
const isSelected = selectedMdAgents.includes(agent.name)
const catColor = agent.category === 'offensive' ? 'cyan'
: agent.category === 'analysis' ? 'yellow'
: agent.category === 'defensive' ? 'blue' : 'gray'
const agentKey = agent.name.replace(/\.md$/, '').replace(/_/g, '_')
const ls = learningStats[agentKey]
return (
<label
key={agent.name}
className={`flex items-center gap-2 p-2 rounded-lg cursor-pointer border transition-colors ${
isSelected
? `bg-${catColor}-500/15 border-${catColor}-500/40 text-${catColor}-400`
: 'bg-dark-800 border-dark-700 text-dark-400 hover:border-dark-500'
}`}
>
<input
type="checkbox"
checked={isSelected}
onChange={() => {
setSelectedMdAgents(prev =>
isSelected ? prev.filter(n => n !== agent.name) : [...prev, agent.name]
)
}}
disabled={isRunning}
className="w-3.5 h-3.5 rounded bg-dark-900 border-dark-600 text-cyan-500 focus:ring-cyan-500"
/>
<div className="min-w-0 flex-1">
<span className="text-xs font-medium block truncate">{agent.display_name}</span>
<div className="flex items-center gap-1.5">
<span className="text-[10px] text-dark-500 capitalize">{agent.category}</span>
{ls && (ls.tp > 0 || ls.fp > 0) && (
<span className="text-[9px] font-mono">
{ls.tp > 0 && <span className="text-green-400">{ls.tp}TP</span>}
{ls.tp > 0 && ls.fp > 0 && <span className="text-dark-600">/</span>}
{ls.fp > 0 && <span className="text-red-400">{ls.fp}FP</span>}
</span>
)}
</div>
</div>
</label>
)
})}
</div>
{selectedMdAgents.length > 0 && (
<button
type="button"
onClick={() => setSelectedMdAgents([])}
className="mt-2 text-xs text-dark-500 hover:text-dark-300 transition-colors"
>
Clear selection (use all agents)
</button>
)}
</div>
)}
</div>
)}
{/* LLM Provider / Model Selection */}
{availableModels.length > 0 && (
<div className="mb-6 flex flex-col sm:flex-row gap-3 sm:gap-4">
+2 -1
View File
@@ -382,7 +382,7 @@ export const agentApi = {
},
// One-click auto pentest
autoPentest: async (target: string, options?: { subdomain_discovery?: boolean; targets?: string[]; auth_type?: string; auth_value?: string; prompt?: string; enable_kali_sandbox?: boolean; custom_prompt_ids?: string[]; preferred_provider?: string; preferred_model?: string; mode?: string; enable_cli_agent?: boolean; cli_agent_provider?: string; methodology_file?: string }): Promise<AgentResponse> => {
autoPentest: async (target: string, options?: { subdomain_discovery?: boolean; targets?: string[]; auth_type?: string; auth_value?: string; prompt?: string; enable_kali_sandbox?: boolean; custom_prompt_ids?: string[]; preferred_provider?: string; preferred_model?: string; mode?: string; enable_cli_agent?: boolean; cli_agent_provider?: string; methodology_file?: string; selected_md_agents?: string[] }): Promise<AgentResponse> => {
const response = await api.post('/agent/run', {
target,
mode: options?.mode || 'auto_pentest',
@@ -398,6 +398,7 @@ export const agentApi = {
enable_cli_agent: options?.enable_cli_agent || false,
cli_agent_provider: options?.cli_agent_provider || undefined,
methodology_file: options?.methodology_file || undefined,
selected_md_agents: options?.selected_md_agents || undefined,
})
return response.data
},