
Scanner di Valutazione delle Vulnerabilità con Generazione di Report
Una piattaforma automatizzata di valutazione delle vulnerabilità che orchestra 86 strumenti di sicurezza open-source, aggrega e deduplica i risultati, esegue un facoltativo livello di analisi LLM compatibile con OpenAI per triage, clustering e remediation, genera script proof-of-concept e produce report professionali in Markdown, HTML e JSON — tutto da una singola immagine Docker BlackArch Linux.
config.toml / env vars / CLI args ↓ AppConfig (pydantic, 3-layer merge: TOML < env < CLI) ↓ Plugin loader — auto-discovers ./plugins/ + ~/.vuln-scanner/plugins/ ↓ ScanOrchestrator • classify_target() → TargetType • tool.applies_to(target) — skips mismatched pairs • asyncio + ThreadPoolExecutor — parallel (tool × target) tasks • AuthConfig forwarded to every applicable tool ↓ ScanResult[] → Assessment ↓ LLMAnalyzer (optional) • Pass 1: triage + PoC design (threaded, per result) • Pass 2: PoC generation (PocGenerator, host-safe) • Pass 3: mitigation (evidence-informed) • Pass 4: clustering + exec summary ↓ PocRunner (container-only, VS_IN_CONTAINER=1 guard) ↓ ┌────────┬────────┬────────┐ │ .md │ .html │ .json │ (all formats written in parallel) └────────┴────────┴────────┘ ↓ DefectDojo (optional)
Tutti gli strumenti di scansione e l'esecuzione dei PoC vengono eseguiti all'interno di un container Docker **BlackArch Linux** — non viene installato nulla sull'host.
---
## Strumenti
86 strumenti organizzati per categoria. Ogni strumento dichiara i tipi di target supportati; l'orchestratore salta automaticamente le combinazioni incompatibili.
### Scansione di Rete e Porte
| Tool | Note |
|------|-------|
| `nmap` | Scansione completa delle porte con rilevamento di servizi/versioni |
| `rustscan` | Scanner di porte veloce, alimenta nmap |
| `masscan` | Scanner TCP/UDP ad alta velocità |
| `naabu` | Scanner di porte con rilevamento dei servizi |
| `netdiscover` | Scoperta host basata su ARP |
### Applicazioni Web
| Tool | Note |
|------|-------|
| `nuclei` | Scanner di vulnerabilità basato su template |
| `nikto` | Scanner di configurazioni errate del server web |
| `wapiti` | Scanner di vulnerabilità web black-box |
| `ffuf` | Fuzzer web veloce (directory, parametri, header) |
| `feroxbuster` | Scoperta di contenuti con ricorsione |
| `gobuster` | Brute-forcer per URI/DNS/vhost |
| `wfuzz` | Fuzzer per applicazioni web |
| `dalfox` | Scanner XSS con analisi dei parametri |
| `xsstrike` | Motore avanzato di rilevamento XSS |
| `commix` | Exploiter di command injection |
| `sqlmap` | SQL injection automatizzata e takeover |
| `nosqlmap` | Scanner per injection NoSQL |
| `httpx` | Probing HTTP e fingerprinting |
| `whatweb` | Fingerprinter delle tecnologie web |
| `wafw00f` | Rilevamento e fingerprinting WAF |
| `wpscan` | Scanner di vulnerabilità WordPress |
| `acunetix` | Scanner di vulnerabilità web (basato su API) |
| `arachni` | Scanner di sicurezza per applicazioni web |
| `zap` | Scanner DAST OWASP ZAP |
| `wapiti` | Scanner di vulnerabilità black-box |
| `drheader` | Analizzatore di header di sicurezza HTTP |
| `humble` | Controllo sicurezza header HTTP |
| `hakrawler` | Crawler web veloce per URL ed endpoint |
| `katana` | Framework di web crawling di nuova generazione |
| `gau` | Collettore di URL noti (AlienVault, WaybackMachine) |
| `jsluice` | Estrattore di segreti e URL da JavaScript |
| `corscanner` | Scanner di configurazioni errate CORS |
| `crlfuzz` | Scanner di injection CRLF |
| `smuggler` | Rilevatore di HTTP request smuggling |
| `linkfinder` | Scoperta di endpoint in sorgenti JavaScript/HTML |
| `cariddi` | Crawler web con rilevamento di segreti ed endpoint |
### API e GraphQL
| Tool | Note |
|------|-------|
| `kiterunner` | Scoperta di rotte API con file kite |
| `graphql_cop` | Auditor di sicurezza GraphQL |
| `restler` | Fuzzer API REST stateful |
| `apifuzzer` | Fuzzer basato su OpenAPI/Swagger |
| `cherrybomb` | Linter di sicurezza per specifiche OpenAPI |
| `arjun` | Scoperta di parametri HTTP |
| `paramspider` | Mining di parametri da wayback/sorgenti |
### DNS e Ricognizione
| Tool | Note |
|------|-------|
| `amass` | Enumerazione di sottodomini (passiva + attiva) |
| `subfinder` | Enumerazione passiva di sottodomini veloce |
| `dnsx` | Toolkit di resolver e probe DNS |
| `dnsrecon` | Enumerazione DNS e zone transfer |
| `fierce` | Ricognizione DNS e scoperta host |
| `theharvester` | OSINT: email, nomi, host, sottodomini |
| `puredns` | Brute-forcer veloce di sottodomini con filtro wildcard |
| `alterx` | Motore di permutazione dei sottodomini |
| `waybackurls` | Raccolta di URL storici da Wayback Machine |
| `httprobe` | Prober di host HTTP/HTTPS attivi |
### TLS / SSL
| Tool | Note |
|------|-------|
| `testssl` | Audit della configurazione TLS e delle suite di cifratura |
| `sslyze` | Scanner TLS (suite di cifratura, Heartbleed, ROBOT) |
| `sslscan` | Scanner per servizi SSL/TLS |
| `tlsx` | Probing TLS veloce |
| `tls_attacker` | Strumento di attacco al protocollo TLS |
| `ssh_audit` | Auditor di configurazione e algoritmi SSH |
### SMB e Servizi di Rete
| Tool | Note |
|------|-------|
| `smbmap` | Enumerazione di condivisioni SMB e permessi |
| `enum4linux` | Enumerazione SMB/NetBIOS |
| `crackmapexec` | Valutazione di Active Directory e SMB |
| `openvas` | Scanner di vulnerabilità OpenVAS |
### SAST e Analisi del Codice
| Tool | Note |
|------|-------|
| `bandit` | SAST Python — anti-pattern di sicurezza comuni |
| `semgrep` | SAST multi-linguaggio con regole della community |
| `gosec` | Controllo di sicurezza per Go |
| `bearer` | SAST data-flow con regole di privacy e sicurezza |
| `horusec` | Motore SAST multi-linguaggio |
| `brakeman` | Scanner SAST per Ruby on Rails |
| `flawfinder` | Analisi statica C/C++ per difetti comuni |
| `dependency_check` | Scanner di vulnerabilità delle dipendenze OWASP |
| `pip_audit` | Controllo vulnerabilità dei pacchetti Python |
### Software Composition Analysis (SCA)
| Tool | Note |
|------|-------|
| `osv-scanner` | Scanner del database di vulnerabilità open source |
| `npm-audit` | Audit di vulnerabilità dei pacchetti Node.js |
| `govulncheck` | Controllo vulnerabilità dei moduli Go |
### Rilevamento Segreti
| Tool | Note |
|------|-------|
| `gitleaks` | Scanner di segreti nella cronologia Git |
| `trufflehog` | Trova segreti basato su entropia profonda |
| `secretfinder` | Segreti in file JS ed endpoint |
| `detect-secrets` | Scanner di segreti basato su baseline |
| `noseyparker` | Scanner di segreti ad alta velocità con regole di pattern |
### IaC e Configurazione
| Tool | Note |
|------|-------|
| `checkov` | Scanner IaC per Terraform/K8s/Dockerfile |
| `tfsec` | Analisi statica Terraform |
| `terrascan` | Scanner di sicurezza IaC multi-cloud |
| `hadolint` | Linter delle best practice per Dockerfile |
### Infrastruttura Cloud
| Tool | Note |
|------|-------|
| `prowler` | Valutazione della postura di sicurezza AWS/GCP/Azure |
| `kube-bench` | Controllo del CIS Kubernetes Benchmark |
### Container e Supply Chain
| Tool | Note |
|------|-------|
| `trivy` | Scanner di vulnerabilità per immagini container + filesystem |
| `grype` | Corrispondenza di vulnerabilità per container e pacchetti |
---
## Filtro per Tipo di Target
L'orchestratore classifica ogni target in uno o più tipi ed esegue solo gli strumenti che dichiarano supporto per quel tipo. Ciò elimina il rumore, ad esempio, degli strumenti SMB eseguiti su URL web.
| Tipo | Esempio | Strumenti corrispondenti |
|------|---------|-----------------|
| `HOST` | `example.com` | strumenti DNS, SSL, web, SMB |
| `IP` | `10.0.0.1` | strumenti di rete, porte, SMB |
| `CIDR` | `10.0.0.0/24` | scanner di rete |
| `URL` | `https://app.example.com` | strumenti web, API, SSL |
| `PATH` | `/src/myapp` | strumenti SAST, SCA, segreti, IaC |
| `REPO` | `https://github.com/org/repo` | strumenti per segreti, SAST, SCA |
| `IMAGE` | `myapp:latest` | scanner per container |
| `CLOUD` | `aws:profile=prod`, `arn:aws:…` | strumenti per la postura cloud (prowler, kube-bench, terrascan) |
La classificazione è automatica: basta passare la stringa del target; lo scanner determina il tipo.
Formati di target cloud riconosciuti:
- ARN AWS: `arn:aws:iam::123456789012:root`
- Abbreviazione per profilo nominato: `aws:profile=production`
- Progetto GCP: `projects/my-project-id`
- UUID di sottoscrizione Azure: `00000000-0000-0000-0000-000000000000`
---
## Modalità di Scansione
| Modalità | Descrizione |
|------|-------------|
| `paranoid` | Massima stealth — probing passivo, impronta minima |
| `passive` | Nessun attacco attivo — solo enumerazione e banner grabbing **(predefinita)** |
| `active` | Controlli di vulnerabilità standard abilitati |
| `aggressive` | Scansione completa: tutti i template, brute-force, timing rapido |
---
## Scansione Autenticata
Le credenziali vengono inoltrate a tutti gli strumenti web applicabili (nuclei, ffuf, feroxbuster, gobuster, nikto, sqlmap, dalfox, wpscan, wapiti, katana, hakrawler, arjun, wfuzz, corscanner, kiterunner, httpx).
### Credenziali globali
Applicate a ogni target, a meno che non esista un override specifico per target.
**Tramite config:**```toml
[scan.auth]
bearer_token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
username = "admin"
password = "secret"
[scan.auth.cookies]
session = "abc123"
[scan.auth.headers]
X-API-Key = "my-api-key"
Tramite variabili d'ambiente (solo a livello globale):```bash VS_AUTH_BEARER_TOKEN=eyJ... VS_AUTH_USERNAME=admin VS_AUTH_PASSWORD=secret
**Via CLI** (solo globale):```bash
vuln-scanner --targets https://app.example.com \
--auth-bearer eyJ... \
--auth-cookie session=abc123 \
--auth-header X-API-Key=secret
Quando si analizzano più target che richiedono credenziali diverse, definisci override per target sotto [scan.auth.targets."<target>"]. Una voce corrispondente sostituisce interamente la configurazione globale per quel target — non c'è unione. L'autenticazione per target è disponibile solo tramite file di configurazione (le variabili d'ambiente e i flag CLI impostano solo il valore predefinito globale).```toml
[scan.auth]
bearer_token = "default-token"
[scan.auth.targets."https://app.example.com"] bearer_token = "app-specific-jwt"
[scan.auth.targets."https://admin.example.com"] [scan.auth.targets."https://admin.example.com".cookies] session = "s%3Aabc123" csrftoken = "xyz789"
[scan.auth.targets."10.0.0.50"] username = "apiuser" password = "s3cret"
[scan.auth.targets."https://legacy.example.com"] login_url = "https://legacy.example.com/login" username = "admin" password = "password123" [scan.auth.targets."https://legacy.example.com".login_data] _token = "csrf-value-here"
**Resolution:** `per-target config > global config`
---
## LLM Analysis
Quando è presente una chiave API, il livello LLM si attiva automaticamente. Esegue quattro passaggi sui risultati della scansione:
| Pass | Name | What it does |
|------|------|-------------|
| 1 | **Triage** | Assegna CWE, confidenza, flag di falso positivo, riepilogo di sfruttabilità e progetta un PoC per ogni risultato |
| 2 | **PoC generation** | Scrive script Python/Bash autocontenuti che confermano il risultato utilizzando strumenti già presenti nel container |
| 3 | **Mitigation** | Produce mitigazioni concrete a breve termine e remediation permanenti, eventualmente basate sulle evidenze del PoC |
| 4 | **Clustering** | Raggruppa i risultati per causa principale, scrive remediation condivise e produce un riepilogo esecutivo |
### Configurazione del provider
Il client LLM è compatibile con l'API OpenAI — funziona con OpenAI, Azure OpenAI, Ollama, vLLM, LM Studio, OpenRouter e qualsiasi altro endpoint compatibile.```toml
[llm]
enabled = "auto" # "auto" | true | false (auto = on when api_key present)
api_key = "" # or set OPENAI_API_KEY env var
base_url = "" # leave empty for OpenAI; set for Ollama/vLLM/etc.
model = "gpt-4o" # REQUIRED when LLM is active — no default
# Sampling parameters (all OpenAI-compatible)
temperature = 0.2
top_p = 0.95
max_tokens = 4096
# top_k and other non-standard params go in extra_body:
# [llm.extra_body]
# top_k = 40
Esempio Ollama:```toml [llm] base_url = "http://localhost:11434/v1" api_key = "ollama" model = "llama3.2"
**vLLM esempio:**```toml
[llm]
base_url = "http://localhost:8000/v1"
api_key = "token-abc123"
model = "meta-llama/Meta-Llama-3-8B-Instruct"
Ogni capacità LLM è una funzionalità nominata, attivabile/disattivabile globalmente e sovrascrivibile per strumento o per categoria.
Configurazione globale delle funzionalità:```toml [llm.features] generate_poc = true execute_poc = false # enable only inside Docker
[llm.features.tool.bandit] generate_poc = false
[llm.features.category.web] logs_analysis = false
**Feature precedence:** `tool override > category override > global`
### Prompt personalizzati
Tutti i prompt LLM sono sovrascrivibili:```toml
[llm.prompts]
enrich_system = "You are a senior penetration tester..."
mitigation_user = "Write remediation steps for: {title}..."
# Available placeholders: {title} {severity} {description} {cwe}
# {exploitability} {tool} {target} {cves} {raw_output}
[llm] include_tools = [] # empty = all tools exclude_tools = ["hakrawler", "gau"] include_categories = [] exclude_categories = ["dns"]
---
## Generazione ed esecuzione del PoC
### Generazione (sempre sicura per l'host)
L'LLM scrive script Python e/o Bash autocontenuti per ogni finding. Gli script utilizzano strumenti già presenti nell'immagine BlackArch (`curl`, `sqlmap`, `nuclei`, `dalfox`, ecc.) e vengono scritti in `<report>_assets/poc/`. La generazione non esegue mai codice — si limita a scrivere file.```toml
[llm.poc]
languages = ["python", "bash"]
only_severities = ["critical", "high", "medium"]
max_pocs = 20
allow_git_clone = false # permit cloning official exploit PoCs from GitHub
L'esecuzione della PoC è bloccata da due controlli indipendenti:
execute_poc = true in [llm.features]VS_IN_CONTAINER=1 (integrata nell'immagine Docker)Il runner rifiuta silenziosamente se manca uno dei due controlli, quindi non può essere eseguito sull'host. Una denylist statica rifiuta gli script che contengono pattern distruttivi (rm -rf /, mkfs., fork bomb, ecc.) prima dell'esecuzione.```bash
VS_LLM_FEATURE_EXECUTE_POC=true docker compose ... run --rm scanner ...
---
## Sistema di Plugin
Inserisci un file `.py` che definisce una o più sottoclassi di `AbstractTool` in `./plugins/` (o `~/.vuln-scanner/plugins/`) e verranno scoperti automaticamente all'avvio — nessuna modifica al codice necessaria.
**Ordine di rilevamento** (le voci successive sovrascrivono in caso di collisione di nomi):
1. `./plugins/` (relativo alla CWD)
2. `~/.vuln-scanner/plugins/`
3. Directory extra configurate tramite `[plugins] dirs` o `--plugin-dir`
**Plugin di esempio** (`plugins/my_scanner.py`):```python
from vuln_scanner.tools.abstract import AbstractTool
from vuln_scanner.tools.enums import Severity, ScanStatus, TargetType
from vuln_scanner.tools.models import Finding, ScanInput, ScanResult
class MyScannerTool(AbstractTool):
name: str = "my-scanner"
category: str = "web"
# Only runs against URL targets — skipped automatically for IPs, paths, etc.
applicable_targets: frozenset[TargetType] = frozenset({TargetType.URL})
def build_command(self, target: str, scan_input: ScanInput) -> list[str]:
return ["my-scanner", "--target", target, "--json"]
def parse_output(self, raw: str, target: str) -> list[Finding]:
...
Configurazione:```toml [plugins] enabled = true dirs = ["/opt/company-scanners"]
**CLI:**```bash
vuln-scanner --plugin-dir /opt/company-scanners --targets https://app.example.com
Gli strumenti plugin sono registrati globalmente, ma il type-gating dell'orchestratore controlla su quali target ogni plugin viene effettivamente eseguito. Un plugin che dichiara applicable_targets = frozenset({TargetType.URL}) non verrà mai attivato contro un IP o un percorso del filesystem.
Per limitare un plugin a specifiche stringhe target oltre al type-gating (ad es., eseguirlo solo contro un host di staging noto), restituisci ScanStatus.SKIPPED all'interno di run():```python
def run(self, target: str, scan_input: ScanInput) -> ScanResult:
if "staging" not in target:
return ScanResult(tool=self.name, target=target, status=ScanStatus.SKIPPED)
return super().run(target, scan_input)
Non esiste un filtro plugin per-target a livello di configurazione — quella logica appartiene al plugin stesso.
---
## Formati di report
Tre formati vengono generati in parallelo. Seleziona qualsiasi combinazione:```toml
[report]
formats = ["markdown", "html", "json"]
output_dir = "./reports"
Oppure tramite CLI: --formats markdown html json
.md)Report professionale strutturato secondo le convenzioni di pentest del settore:
I risultati di più strumenti che segnalano lo stesso problema sullo stesso target vengono deduplicati in un'unica voce che mostra tutti gli strumenti coinvolti.
.html)Report autonomo a file singolo (nessuna dipendenza esterna) con:
.json)Dump strutturato completo del modello Assessment — risultati, arricchimento LLM, cluster, statistiche, record PoC. Adatto per l'ingestione in pipeline CI/CD e per strumenti a valle.
Lo script poc.sh avvia DefectDojo, tre target vulnerabili e lo scanner con un unico comando.
Prerequisiti: docker, docker compose plugin, curl, `python3````bash
./poc.sh
| Step | Action |
|------|--------|
| 1 | Verifica i prerequisiti |
| 2 | Carica `.env` (lo copia da `.env.example` se mancante) |
| 3 | Avvia lo stack DefectDojo |
| 4 | Attende che l'API di DefectDojo sia pronta |
| 5 | Ottiene il token API tramite le credenziali admin |
| 6 | Avvia i container dei target vulnerabili |
| 7 | Attende che ogni target sia raggiungibile |
| 8 | Costruisce l'immagine Docker dello scanner |
| 9 | Esegue lo scanner, genera i report e li invia a DefectDojo |
| 10 | Mostra il riepilogo con URL e istruzioni di teardown |
**Con analisi LLM:**```bash
# Copy the example env and add your key
cp .env.example .env
# Edit .env: set OPENAI_API_KEY and VS_LLM_MODEL
./poc.sh
Modalità di scansione override:```bash SCAN_MODE=active ./poc.sh
**Smontaggio:**```bash
docker compose down -v
docker compose -f docker-compose.target.yaml down -v
poc.sh)| App | URL | Descrizione |
|---|---|---|
| OWASP Juice Shop | http://localhost:3000 | App Node.js moderna che copre la OWASP Top 10 |
Sistemi disponibili pubblicamente e intenzionalmente vulnerabili, gestiti da pentest-ground.com. Non è richiesta alcuna configurazione — scansiona direttamente per validare gli strumenti e la generazione di PoC.
## scanner.sh — Wrapper Docker
`scanner.sh` è l'interfaccia consigliata per l'uso quotidiano dello scanner. Incapsula `docker compose run` così non devi mai digitare manualmente l'invocazione di compose — basta passare direttamente target e flag.```bash
./scanner.sh [OPTIONS] [-- SCANNER_ARGS...]
Tutto ciò che segue -- viene inoltrato così com'è al punto di ingresso dello scanner, bypassando tutta la logica del wrapper.
./scanner.sh
./scanner.sh -t https://app.example.com 192.168.1.0/24 -m active
./scanner.sh -c /path/to/prod.toml
./scanner.sh -t https://app.example.com --llm-model gpt-4o
./scanner.sh -t https://app.example.com --include-tools nuclei,dalfox,ffuf
./scanner.sh --build -t https://app.example.com -m active
./scanner.sh -- --targets https://t.example.com --mode aggressive --formats markdown html json
./scanner.sh --shell ./scanner.sh --build --shell
### Cosa fa automaticamente
- Carica `.env` (copia da `.env.example` se manca)
- Copia `config.example.toml` → `config.toml` se non esiste alcuna configurazione
- Crea la rete Docker `vuln_scanner_network` se non è presente
- Monta un file `--config` personalizzato nel container in `/app/config.toml`
- Ricostruisce l'immagine quando viene passato `--build`
---
## Configurazione
Copia il modello annotato:```bash
cp config.example.toml config.toml
Riferimento completo:```toml [scan] targets = ["192.168.1.1", "https://app.example.com", "/src/myapp"] mode = "passive" # paranoid | passive | active | aggressive timeout = 300 # per-tool timeout in seconds rate_limit = null # requests/sec; null = no limit
[scan.auth] bearer_token = "" # Authorization: Bearer username = "" # HTTP Basic username password = "" # HTTP Basic password login_url = "" # Form-based login URL
[tools] exclude = ["nikto"] # skip specific tools by name
[categories] include = ["web", "ssl"] # limit to these categories; empty = all
[plugins] enabled = true
[report] formats = ["markdown", "html", "json"] output_dir = "./reports"
[defectdojo] url = "http://localhost:8080" api_key = "" product_name = "My Product" engagement_name = "Automated Scan"
[llm] enabled = "auto" # "auto" | true | false api_key = "" # or OPENAI_API_KEY env var base_url = "" # leave empty for OpenAI model = "" # required when active, e.g. "gpt-4o" or "llama3.2" temperature = 0.2 top_p = 0.95 max_tokens = 4096
exclude_tools = [] exclude_categories = []
[llm.features] logs_analysis = true enrich = true classify = true cluster = true mitigation = true generate_poc = true execute_poc = false # container-only; set VS_LLM_FEATURE_EXECUTE_POC=true false_positive_filter = true
[llm.features.tool.bandit] generate_poc = false
[llm.features.category.dns] logs_analysis = false
[llm.poc] languages = ["python", "bash"] only_severities = ["critical", "high", "medium"] max_pocs = 20 allow_git_clone = false
**Precedenza di unione della configurazione:** `CLI > env vars > config.toml > defaults`
---
## Variabili d'ambiente
### Core
| Variable | CLI flag | Description |
|----------|----------|-------------|
| `VS_TARGETS` | `--targets` | Elenco di target separati da spazi |
| `VS_MODE` | `--mode` | Modalità di scansione |
| `VS_TIMEOUT` | `--timeout` | Timeout per strumento (secondi) |
| `VS_RATE_LIMIT` | `--rate-limit` | Limite di frequenza (req/s) |
| `VS_MAX_CONCURRENT` | `--max-concurrent` | Slot strumenti paralleli |
| `VS_INCLUDE_TOOLS` | `--include-tools` | Strumenti in whitelist per nome |
| `VS_EXCLUDE_TOOLS` | `--exclude-tools` | Strumenti in blacklist per nome |
| `VS_INCLUDE_CATEGORIES` | `--include-categories` | Categorie in whitelist |
| `VS_EXCLUDE_CATEGORIES` | `--exclude-categories` | Categorie in blacklist |
| `VS_OUTPUT_DIR` | `--output-dir` | Directory di output dei report |
### Report
| Variable | CLI flag | Description |
|----------|----------|-------------|
| `VS_FORMATS` | `--formats` | Formati di report: `markdown html json` |
### LLM
| Variable | CLI flag | Description |
|----------|----------|-------------|
| `OPENAI_API_KEY` | — | Chiave API (variabile d'ambiente standard, usata come fallback) |
| `OPENAI_BASE_URL` | — | URL di base di fallback (per endpoint non OpenAI) |
| `VS_LLM_ENABLED` | `--no-llm` | `auto` \| `true` \| `false` |
| `VS_LLM_MODEL` | `--llm-model` | Nome del modello (richiesto quando attivo) |
| `VS_LLM_TEMPERATURE` | — | Temperatura di campionamento |
| `VS_LLM_MAX_TOKENS` | — | Token massimi di output |
| `VS_LLM_FEATURE_<NAME>` | `--llm-feature NAME=on` | Interruttore globale per le funzionalità, ad es. `VS_LLM_FEATURE_GENERATE_POC=false` |
| `VS_LLM_FEATURE_EXECUTE_POC` | `--llm-poc-execute` | Abilita l'esecuzione di PoC (solo container) |
### Scansione autenticata
| Variable | CLI flag | Description |
|----------|----------|-------------|
| `VS_AUTH_BEARER_TOKEN` | `--auth-bearer` | Token Bearer (`Authorization: Bearer …`) |
| `VS_AUTH_USERNAME` | `--auth-user` | Nome utente HTTP Basic |
| `VS_AUTH_PASSWORD` | `--auth-pass` | Password HTTP Basic |
| `VS_AUTH_LOGIN_URL` | `--auth-login-url` | URL di accesso basato su modulo |
I cookie e le intestazioni aggiuntive devono essere impostati tramite file di configurazione o flag CLI `--auth-cookie` / `--auth-header`.
### Plugin
| Variable | CLI flag | Description |
|----------|----------|-------------|
| `VS_PLUGINS_ENABLED` | `--no-plugins` | Abilita/disabilita l'auto-discovery dei plugin |
| `VS_PLUGINS_DIRS` | `--plugin-dir` | Directory plugin aggiuntive (separate da spazi) |
### DefectDojo
| Variable | CLI flag | Description |
|----------|----------|-------------|
| `VS_DEFECTDOJO_URL` | `--defectdojo-url` | URL di base di DefectDojo |
| `VS_DEFECTDOJO_API_KEY` | `--defectdojo-api-key` | Token API |
| `VS_DEFECTDOJO_PRODUCT` | — | Nome del prodotto |
| `VS_DEFECTDOJO_ENGAGEMENT` | — | Nome dell'engagement |
---
## Struttura del progetto```
vuln_scanner/
├── config/
│ ├── models.py # AppConfig, AppLLMConfig, PluginsConfig (pydantic)
│ └── loader.py # 3-layer merge: TOML + env (VS_*) + CLI
│
├── tools/
│ ├── enums.py # Severity, Confidence, ScanStatus, ScanMode, TargetType
│ ├── models.py # Finding, ScanInput, ScanResult, AuthConfig (pydantic)
│ ├── target.py # classify_target() — maps target string to TargetType set
│ ├── abstract.py # AbstractTool ABC + subprocess execution helpers
│ ├── __init__.py # TOOL_REGISTRY (86 tools)
│ └── <tool>.py # One file per tool (86 total)
│
├── llm/
│ ├── models.py # LLMConfig, LLMFeatures, PocConfig (pydantic)
│ ├── features.py # resolve_features() — tool > category > global merge
│ ├── client.py # LLMClient — thin openai SDK wrapper
│ ├── analyzer.py # LLMAnalyzer — 4-pass analysis pipeline
│ └── prompts.py # Default prompt templates (all overridable)
│
├── poc/
│ ├── models.py # Poc, PocVerdict
│ ├── generator.py # PocGenerator — writes scripts, never executes (host-safe)
│ └── runner.py # PocRunner — executes scripts (VS_IN_CONTAINER guard)
│
├── reports/
│ ├── base.py # AbstractReporter
│ ├── markdown.py # Professional structured Markdown report
│ ├── html.py # Self-contained HTML with light/dark theme
│ └── json_reporter.py # Full Assessment JSON dump
│
├── defectdojo/
│ └── client.py # DefectDojoClient — push findings via REST API
│
├── plugins.py # Plugin auto-discovery (./plugins/, ~/.vuln-scanner/plugins/)
├── model.py # Assessment, Cluster, AssessmentStats
└── orchestrator.py # ScanOrchestrator — type-gated, async concurrent execution
plugins/ # Drop .py plugin files here (auto-discovered at startup)
main.py # Entry point
config.example.toml # Fully documented configuration template
.env.example # Environment variable reference
Dockerfile # BlackArch-based image; bakes VS_IN_CONTAINER=1
docker-compose.yaml # DefectDojo stack
docker-compose.scanner.yaml # Scanner service
docker-compose.target.yaml # Vulnerable test targets (Juice Shop, WebGoat)
scanner.sh # Convenience wrapper — runs the scanner via docker compose
poc.sh # End-to-end quick-start script (DefectDojo + targets + scanner)
Per strumenti usa-e-getta o privati, utilizza il Plugin System — inserisci un file .py nella cartella ./plugins/ senza modifiche al codice. Per gli strumenti che dovrebbero essere inclusi nel progetto:
vuln_scanner/tools/mytool.py:```python
from vuln_scanner.tools.abstract import AbstractTool
from vuln_scanner.tools.enums import Severity, TargetType
from vuln_scanner.tools.models import Finding, ScanInputclass MyTool(AbstractTool): name: str = "mytool" category: str = "web" # Declare which target types this tool supports. # The orchestrator skips mismatched (tool, target) pairs automatically. applicable_targets: frozenset[TargetType] = frozenset({TargetType.URL, TargetType.HOST})
def build_command(self, target: str, scan_input: ScanInput) -> list[str]:
return ["mytool", "--target", target]
def parse_output(self, raw: str, target: str) -> list[Finding]:
findings = []
for line in raw.splitlines():
if "VULN" in line:
findings.append(Finding(
title="Example finding",
severity=Severity.HIGH,
description=line,
tool=self.name,
target=target,
))
return findings
2. Registralo in `vuln_scanner/tools/__init__.py`:```python
from vuln_scanner.tools.mytool import MyTool
TOOL_REGISTRY: dict[str, type[AbstractTool]] = {
...
"mytool": MyTool,
}
Dockerfile:```dockerfile
RUN pacman -Sy --noconfirm mytool**Suggerimenti:**
- Per gli strumenti che scrivono su un file invece che su stdout, usa `OUTPUT_FILE_SENTINEL` in `build_command()` e ridefinisci `run()` per chiamare `self._run_with_tempfile()`.
- Gli strumenti con `applicable_targets = frozenset(TargetType)` (l'impostazione predefinita) vengono eseguiti su tutti i tipi di target — usala solo per strumenti davvero universali.
- Binario non trovato → `ScanStatus.SKIPPED` (non mostrato nel report). Errore dello strumento → `ScanStatus.FAILED` (mostrato nell'Appendice A).
---
## Sviluppo```bash
# Install with dev dependencies
uv sync
# Run tests (host-safe only — no real tool execution)
uv run pytest tests/ -v
# Lint
uv run ruff check .
uv run ruff format .
Categorie di test:
tests/test_config.py — unione e validazione della configurazionetests/test_target_typing.py — classify_target() e applies_to()tests/test_orchestrator_gating.py — gating per tipo con strumenti mocktests/test_llm.py — funzionalità LLM, client mockato, guardia container del PoC runnertests/test_reports.py — tutti e tre i reporter (Markdown, HTML, JSON)tests/test_nmap.py — parser dell'output nmapRegola di sicurezza: non eseguire mai strumenti di scansione reali sull'host. Tutta l'esecuzione degli strumenti avviene all'interno del container Docker contro i container target isolati. Il PocRunner impone questa regola: verifica VS_IN_CONTAINER=1 prima di eseguire qualsiasi script PoC, e l'immagine Docker include questa variabile.
I findings vengono inviati automaticamente quando api_key e product_name sono configurati.
Ottieni la tua API key:
admin / admin)Invio manuale:```bash
VS_DEFECTDOJO_API_KEY=your-key
VS_DEFECTDOJO_PRODUCT="My App"
uv run vuln-scanner --targets 192.168.1.1
| Funzionalità | Predefinito | Descrizione |
|---|
logs_analysis | on | Fornisci l'output grezzo dello strumento al LLM |
enrich | on | Triage CWE / confidenza / falsi positivi / sfruttabilità |
classify | on | Classifica il tipo di finding e il rischio |
cluster | on | Raggruppa i finding per causa radice |
mitigation | on | Genera mitigazione e remediation |
generate_poc | on | Scrivi script PoC come asset del report |
execute_poc | off | Esegui PoC nel contenitore (richiede VS_IN_CONTAINER=1) |
false_positive_filter | on | Sopprimi i falsi positivi probabili dal report |
| WebGoat | http://localhost:8888/WebGoat | App Java/Spring intenzionalmente insicura |
| Sistema | URL | Tipo | Classi di vulnerabilità |
|---|
| DVWA | https://pentest-ground.com:4280 | App Web classica | CSRF, XSS, SQLi |
| DVGQL | https://pentest-ground.com:5013 | API GraphQL | CMDi, XSS, SQLi |
| RestFlaw | https://pentest-ground.com:9000 | API REST | SQLi, Iniezione di codice, XXE |
| GuardianLeaks | https://pentest-ground.com:81 | App Web | XSS, SSRF, Iniezione di codice |
| vuln-scanner --targets \ | |||
| https://pentest-ground.com:4280 \ | |||
| https://pentest-ground.com:5013 \ | |||
| https://pentest-ground.com:9000 \ | |||
| https://pentest-ground.com:81 \ | |||
| --mode active |
| Flag | Descrizione |
|---|
-t, --targets HOST... | Uno o più target di scansione (URL, IP, CIDR, percorso, immagine) |
-m, --mode MODE | Modalità di scansione: passive | active | aggressive | paranoid |
-c, --config FILE | File di configurazione da montare (default: ./config.toml) |
-f, --formats FMT | Formati di report, separati da virgola: markdown,html,json; ripetibile |
--no-llm | Disabilita l'arricchimento LLM |
--llm-model MODEL | Override del modello LLM (es. gpt-4o, claude-sonnet-4-5) |
--llm-min-severity SEV | Severità minima per LLM: info|low|medium|high|critical |
--include-tools TOOLS | Elenco separato da virgole di strumenti da eseguire |
--exclude-tools TOOLS | Elenco separato da virgole di strumenti da saltare |
-e, --env KEY=VALUE | Passa una variabile d'ambiente extra al container |
-b, --build | Ricostruisci l'immagine Docker prima dell'esecuzione |
-n, --no-defectdojo | Salta l'integrazione con DefectDojo |
--shell | Apre una shell interattiva all'interno del container invece di eseguire la scansione |
-h, --help | Mostra l'aiuto |