mirror of
https://github.com/Vyntral/god-eye.git
synced 2026-05-16 21:43:34 +02:00
3a4c230aa7
Complete architectural overhaul. Replaces the v0.1 monolithic scanner with an event-driven pipeline of auto-registered modules. Foundation (internal/): - eventbus: typed pub/sub, 20 event types, race-safe, drop counter - module: registry with phase-based selection - store: thread-safe host store with per-host locks + deep-copy reads - pipeline: coordinator with phase barriers + panic recovery - config: 5 scan profiles + 3 AI tiers + YAML loader + auto-discovery Modules (26 auto-registered across 6 phases): - Discovery: passive (26 sources), bruteforce, recursive, AXFR, GitHub dorks, CT streaming, permutation, reverse DNS, vhost, ASN, supply chain (npm + PyPI) - Enrichment: HTTP probe + tech fingerprint + TLS appliance ID, ports - Analysis: security checks, takeover (110+ sigs), cloud, JavaScript, GraphQL, JWT, headers (OWASP), HTTP smuggling, AI cascade, Nuclei - Reporting: TXT/JSON/CSV writer + AI scan brief AI layer (internal/ai/ + internal/modules/ai/): - Three profiles: lean (16 GB), balanced (32 GB MoE), heavy (64 GB) - Six event-driven handlers: CVE, JS file, HTTP response, secret filter, multi-agent vuln enrichment, anomaly + executive report - Content-hash cache dedups Ollama calls across hosts - Auto-pull of missing models via /api/pull with streaming progress - End-of-scan AI SCAN BRIEF in terminal with top chains + next actions Nuclei compat layer (internal/nucleitpl/): - Executes ~13k community templates (HTTP subset) - Auto-download of nuclei-templates ZIP to ~/.god-eye/nuclei-templates - Scope filter rejects off-host templates (eliminates OSINT FPs) Operations: - Interactive wizard (internal/wizard/) — zero-flag launch - LivePrinter (internal/tui/) — colorized event stream - Diff engine + scheduler (internal/diff, internal/scheduler) for continuous ASM monitoring with webhook alerts - Proxy support (internal/proxyconf/): http / https / socks5 / socks5h + basic auth Fixes #1 — native SOCKS5 / Tor compatibility via --proxy flag. 185 unit tests across 15 packages, all race-detector clean.
209 lines
6.1 KiB
Go
209 lines
6.1 KiB
Go
package config
|
|
|
|
// Profile is a named bundle of defaults that tailors God's Eye for a specific
|
|
// use case. Profiles set module enable/disable, concurrency hints, stealth,
|
|
// and whether AI is on. CLI flags still override profile defaults.
|
|
type Profile struct {
|
|
Name string
|
|
Description string
|
|
|
|
// Core tuning
|
|
Concurrency int
|
|
Timeout int
|
|
Stealth string // off, light, moderate, aggressive, paranoid
|
|
|
|
// Feature toggles (nil means "use module default")
|
|
AI *bool
|
|
MultiAgent *bool
|
|
Recursive *bool
|
|
NoBrute *bool
|
|
NoProbe *bool
|
|
NoPorts *bool
|
|
NoTakeover *bool
|
|
|
|
// Advanced feature flags (nil = use module default)
|
|
CloudScan *bool
|
|
APIScan *bool
|
|
SecretsScan *bool
|
|
TechScan *bool
|
|
ASNScan *bool
|
|
VHostScan *bool
|
|
|
|
// Per-module overrides (explicit enable/disable)
|
|
Modules map[string]bool
|
|
}
|
|
|
|
// ProfileBugBounty is tuned for bug-bounty recon: broad discovery, AI on,
|
|
// secrets+tech+cloud scanning on, stealth off (speed matters).
|
|
var ProfileBugBounty = Profile{
|
|
Name: "bugbounty",
|
|
Description: "Aggressive recon for bug-bounty: broad discovery, AI on, secrets/cloud/API/tech scanning, stealth off.",
|
|
Concurrency: 1000,
|
|
Timeout: 5,
|
|
Stealth: "off",
|
|
AI: ptrTrue(),
|
|
MultiAgent: ptrTrue(),
|
|
Recursive: ptrTrue(),
|
|
CloudScan: ptrTrue(),
|
|
APIScan: ptrTrue(),
|
|
SecretsScan: ptrTrue(),
|
|
TechScan: ptrTrue(),
|
|
ASNScan: ptrTrue(),
|
|
VHostScan: ptrTrue(),
|
|
}
|
|
|
|
// ProfilePentest is tuned for authorized penetration tests: stealth light,
|
|
// full enrichment, AI on for deeper analysis.
|
|
var ProfilePentest = Profile{
|
|
Name: "pentest",
|
|
Description: "Authorized pentest: full enrichment with light stealth to avoid basic rate limits.",
|
|
Concurrency: 300,
|
|
Timeout: 10,
|
|
Stealth: "light",
|
|
AI: ptrTrue(),
|
|
MultiAgent: ptrTrue(),
|
|
Recursive: ptrTrue(),
|
|
CloudScan: ptrTrue(),
|
|
APIScan: ptrTrue(),
|
|
SecretsScan: ptrTrue(),
|
|
TechScan: ptrTrue(),
|
|
ASNScan: ptrTrue(),
|
|
VHostScan: ptrTrue(),
|
|
}
|
|
|
|
// ProfileASMContinuous is tuned for attack-surface monitoring: reduced depth
|
|
// per run, designed to be re-run periodically with diff engine (Fase 5).
|
|
// Stealth moderate to stay below detection thresholds when running daily.
|
|
var ProfileASMContinuous = Profile{
|
|
Name: "asm-continuous",
|
|
Description: "Continuous attack-surface monitoring; runs cheaper than full recon, feeds diff engine.",
|
|
Concurrency: 200,
|
|
Timeout: 10,
|
|
Stealth: "moderate",
|
|
AI: ptrFalse(), // AI only on findings that change, not full re-analysis
|
|
Recursive: ptrFalse(), // rely on diff to grow surface over time
|
|
CloudScan: ptrTrue(),
|
|
TechScan: ptrTrue(),
|
|
SecretsScan: ptrTrue(),
|
|
}
|
|
|
|
// ProfileStealthMax is for highly sensitive targets where any detection is
|
|
// unacceptable. Very slow; passive-first.
|
|
var ProfileStealthMax = Profile{
|
|
Name: "stealth-max",
|
|
Description: "Maximum evasion. Passive-only by default, slow request cadence.",
|
|
Concurrency: 3,
|
|
Timeout: 20,
|
|
Stealth: "paranoid",
|
|
NoBrute: ptrTrue(),
|
|
NoPorts: ptrTrue(),
|
|
AI: ptrFalse(),
|
|
TechScan: ptrTrue(),
|
|
}
|
|
|
|
// ProfileQuick is for triage: skip expensive phases, produce a fast answer.
|
|
var ProfileQuick = Profile{
|
|
Name: "quick",
|
|
Description: "Fast triage: passive enum + HTTP probe, no brute/JS/AI.",
|
|
Concurrency: 500,
|
|
Timeout: 5,
|
|
Stealth: "off",
|
|
NoBrute: ptrTrue(),
|
|
AI: ptrFalse(),
|
|
}
|
|
|
|
// BuiltinProfiles lists every named profile that ships with the tool, in a
|
|
// stable order for docs/help output.
|
|
var BuiltinProfiles = []Profile{
|
|
ProfileBugBounty,
|
|
ProfilePentest,
|
|
ProfileASMContinuous,
|
|
ProfileStealthMax,
|
|
ProfileQuick,
|
|
}
|
|
|
|
// ProfileByName returns the named profile, or ok=false when not found.
|
|
func ProfileByName(name string) (Profile, bool) {
|
|
for _, p := range BuiltinProfiles {
|
|
if p.Name == name {
|
|
return p, true
|
|
}
|
|
}
|
|
return Profile{}, false
|
|
}
|
|
|
|
// ApplyProfile merges a profile into cfg. Existing non-zero values in cfg
|
|
// take precedence (CLI flags win over profile defaults). Pointer-typed
|
|
// profile fields are applied only when they are non-nil.
|
|
func ApplyProfile(cfg *Config, p Profile) {
|
|
if cfg == nil {
|
|
return
|
|
}
|
|
|
|
if cfg.Concurrency == 0 || cfg.Concurrency == 1000 { // 1000 is the cobra default
|
|
cfg.Concurrency = p.Concurrency
|
|
}
|
|
if cfg.Timeout == 0 || cfg.Timeout == 5 { // 5 is cobra default
|
|
cfg.Timeout = p.Timeout
|
|
}
|
|
if cfg.StealthMode == "" {
|
|
cfg.StealthMode = p.Stealth
|
|
}
|
|
|
|
if p.AI != nil && !cfg.EnableAI {
|
|
cfg.EnableAI = *p.AI
|
|
}
|
|
if p.MultiAgent != nil && !cfg.MultiAgent {
|
|
cfg.MultiAgent = *p.MultiAgent
|
|
}
|
|
if p.Recursive != nil && !cfg.Recursive && !cfg.NoRecursive {
|
|
cfg.Recursive = *p.Recursive
|
|
}
|
|
if p.NoBrute != nil && !cfg.NoBrute {
|
|
cfg.NoBrute = *p.NoBrute
|
|
}
|
|
if p.NoProbe != nil && !cfg.NoProbe {
|
|
cfg.NoProbe = *p.NoProbe
|
|
}
|
|
if p.NoPorts != nil && !cfg.NoPorts {
|
|
cfg.NoPorts = *p.NoPorts
|
|
}
|
|
if p.NoTakeover != nil && !cfg.NoTakeover {
|
|
cfg.NoTakeover = *p.NoTakeover
|
|
}
|
|
|
|
applyPtrBool(&cfg.CloudScan, &cfg.NoCloudScan, p.CloudScan)
|
|
applyPtrBool(&cfg.APIScan, &cfg.NoAPIScan, p.APIScan)
|
|
applyPtrBool(&cfg.SecretsScan, &cfg.NoSecrets, p.SecretsScan)
|
|
applyPtrBool(&cfg.TechScan, &cfg.NoTechScan, p.TechScan)
|
|
applyPtrBool(&cfg.ASNScan, &cfg.NoASNScan, p.ASNScan)
|
|
applyPtrBool(&cfg.VHostScan, &cfg.NoVHostScan, p.VHostScan)
|
|
|
|
// Module overrides
|
|
if cfg.ModuleSettings == nil {
|
|
cfg.ModuleSettings = make(map[string]bool)
|
|
}
|
|
for name, enabled := range p.Modules {
|
|
if _, already := cfg.ModuleSettings[name]; !already {
|
|
cfg.ModuleSettings[name] = enabled
|
|
}
|
|
}
|
|
}
|
|
|
|
// applyPtrBool merges a ptr-bool from a profile into a (enabled, noEnabled)
|
|
// pair on the Config struct. The v1 scheme uses two flags per feature
|
|
// (Enable/NoEnable) to allow a three-state: unset/on/off. A nil profile ptr
|
|
// means "leave unchanged"; *p=true enables unless user has set NoX; *p=false
|
|
// leaves alone (profile doesn't force-off, user's explicit flag does).
|
|
func applyPtrBool(enable, disable *bool, p *bool) {
|
|
if p == nil {
|
|
return
|
|
}
|
|
if *p && !*enable && !*disable {
|
|
*enable = true
|
|
}
|
|
}
|
|
|
|
func ptrTrue() *bool { v := true; return &v }
|
|
func ptrFalse() *bool { v := false; return &v }
|