
Piattaforma VAPT ospitata localmente e isolata dalla rete (air-gapped) che esegue 8 moduli di scansione in parallelo, attribuisce punteggi deterministici ai risultati con CVSS v3.1 e genera report PDF con remediation opzionale generata da IA tramite LLM locale.
Realizzato da maverickaayush.
Uno strumento VAPT auto-ospitato e isolato dalla rete (air-gapped): puntalo su un dominio target autorizzato e lancia 8 moduli di scansione in parallelo, valuta in modo deterministico ogni risultato (CVSS v3.1), aggiunge opzionalmente descrizioni in inglese semplice generate dall'IA tramite un LLM locale e produce un report PDF oltre a una dashboard web live. Nessuna chiamata API esterna: tutto gira sulla tua rete.
Due modi per eseguire ONUS:
- Self-hosted (questo repository):
docker compose up→ inserisci un dominio → spunta la casella di autorizzazione → scansiona. Nessun account, nessun accesso, nessuna verifica email: è monoperatore per design, e tutto ciò che segue riguarda questo percorso.- Hosted: un'istanza gestita è disponibile su tryonus.tech. Aggiunge funzionalità solo di produzione (account / accesso OAuth, coda di scansione, cronologia per utente) che in questo repository sono disattivate di default, così l'auto-hosting resta semplice. Vedi Self-hosted vs hosted.
Il percorso self-hosted di default è volutamente il più semplice: nessuna registrazione, nessuna verifica email, nessun OAuth. Le funzionalità solo-hosted (autenticazione, coda di scansione) stanno dietro flag di configurazione che di default sono off (REQUIRE_AUTH=false, HOSTED_QUEUE_ENABLED=false; vedi Configurazione) e non sono impostate in docker-compose.yml - quindi eseguire ONUS localmente non ti mette mai dietro un login. Preferisci zero setup? Usa il sito hosted su tryonus.tech.
| Nuova Scansione | Stato Scansione Live |
|---|---|
![]() | ![]() |
| Dashboard Report | Scoperta Scansioni |
|---|---|
![]() | ![]() |
domain → [recon | webscan | ssl_tls | headers | owasp | tech_fingerprint | nuclei | enumeration] (parallel, Celery)
→ any module failed/timed out? → pause for operator retry/continue/cancel
→ aggregator (dedup + OWASP-map + sort)
→ confidence verification (passive re-observation)
→ deterministic CVSS scoring
→ Ollama (Qwen 2.5 7B) AI analysis
→ WeasyPrint PDF + PostgreSQL
→ dashboard / PDF download
Sei livelli: frontend Next.js → FastAPI → Celery/Redis → 8 moduli di scansione in parallelo → Ollama (Qwen 2.5 7B) → PDF WeasyPrint + dashboard. Dettagli completi in ARCHITECTURE.md (schemi, contratti, salvaguardie) e docs/QUICK_REF.md (riferimento rapido per le modifiche comuni).
mem_limit: 4g), e Postgres, Redis, l'API, il worker e il frontend girano insieme ad esso.Vedi Prerequisiti sopra: ~8GB di disco e ~6GB di RAM, e aspettati una prima compilazione di 10-15 minuti.
cp .env.example .env
cp backend/subfinder-config/provider-config.yaml.example backend/subfinder-config/provider-config.yaml
docker compose up -d
docker compose ps # wait for zap to report healthy (~2 min)
Apri http://localhost:3000, inserisci un dominio, spunta la casella di autorizzazione e avvia la scansione.
Nessun accesso, registrazione o verifica email. ONUS self-hosted è monoperatore di default: non c'è alcun passaggio di account tra l'apertura della dashboard e la scansione.
Funziona senza installare Ollama. La valutazione CVSS/gravità/priorità è sempre deterministica (analysis/cvss_scorer.py) - senza Ollama in esecuzione, i risultati ricevono semplicemente un modello di descrizione basato su regole invece di testo generato dall'IA. Vedi "Opzionale: abilita le descrizioni generate dall'IA" sotto per attivarlo.
Per eseguire questo strumento non serve alcuna chiave API. Ogni strumento di scansione che integra (nmap, ZAP, Nikto, testssl.sh, Nuclei, Amass, Naabu, httpx, WhatWeb, WAFW00F, FFUF) e Ollama stesso funzionano senza alcuna chiave. Il passaggio di copia della configurazione subfinder sopra è l'unica eccezione opzionale: lasciare il template vuoto va bene, subfinder girerà solo con fonti gratuite/pubbliche. Per approfondire l'enumerazione dei sottodomini, puoi aggiungere fino a due chiavi di livello gratuito in quel file prima di iniziare: un personal access token GitHub e una chiave API ProjectDiscovery Chaos - vedi i commenti dentro provider-config.yaml.example.
Ollama gira nativamente sull'host (non in Docker) così può usare direttamente la GPU dell'host; i container lo raggiungono tramite host.docker.internal.
ollama pull qwen2.5:7b127.0.0.1, che la rete bridge di Docker non può raggiungere):
sudo systemctl edit ollama
[Service]:
[Service]
Environment="OLLAMA_HOST=0.0.0.0:11434"
sudo systemctl daemon-reload && sudo systemctl restart ollama
curl http://localhost:11434/api/tagsdocker compose restart backend workerIl file compose definisce anche 12 app di pratica volutamente vulnerabili (Juice Shop, DVWA, bWAPP, Mutillidae, NodeGoat, DVWP/WordPress dietro un WAF ModSecurity, Metasploitable2, WebGoat) per provare lo scanner senza bisogno di un target autorizzato tuo. Sono dietro un profilo Compose, quindi non vengono mai compilate/avviate di default:
docker compose --profile targets up -d
Attenzione: questi sono servizi volutamente vulnerabili, alcuni realmente backdoored (Metasploitable2 include un backdoor vsftpd attivo). Esegui il profilo targets solo su una macchina non raggiungibile da internet o da una rete condivisa - mai su un'istanza cloud pubblica o su un host esposto.
La maggior parte gira da immagini precompilate e non richiede nulla di extra. Due - nodegoat e dvwp-wordpress - vengono compilati da sorgenti non incluse in questo repository e devono essere clonati prima:
git clone https://github.com/OWASP/NodeGoat nodegoat-src
git clone https://github.com/vavkamil/dvwp dvwp-src
Porte pubblicate una volta avviati: Juice Shop :3001, DVWA :8081, bWAPP :8083, Mutillidae :8084, NodeGoat :8085, DVWP (via WAF, TLS) :8444, WebGoat :8082. Metasploitable2 non pubblica alcuna porta host (raggiungibile solo da backend/worker attraverso la rete interna di Docker) poiché espone servizi di rete realmente backdoored/senza autenticazione.
Variabili d'ambiente, impostate tramite .env (copiato da .env.example):
I default di POSTGRES_PASSWORD/SECRET_KEY sopra sono solo dimostrativi - vanno bene per un'istanza locale/personale, ma cambiali entrambi prima di distribuire ovunque raggiungibile da altri. Questo ora è imposto, non solo consigliato: imposta ONUS_ENV=production (o attiva l'autenticazione hosted) e il backend rifiuta di avviarsi finché uno dei due è ancora un default/segnaposto. Genera una chiave forte con python -c "import secrets; print(secrets.token_urlsafe(48))".
Le funzionalità solo-hosted sono disattivate di default. REQUIRE_AUTH (account / accesso OAuth) e HOSTED_QUEUE_ENABLED (coda di scansione) hanno entrambi default false e non sono impostate in docker-compose.yml, quindi ONUS self-hosted non ti mette mai dietro un login o una coda. Lasciale spente a meno che tu non stia intenzionalmente costruendo una distribuzione hosted multiutente: l'istanza gestita tryonus.tech è quella che le attiva.
ONUS non ha analitica di default - nulla viene caricato e nessun dato lascia il browser. Per raccogliere metriche anonime di utilizzo del prodotto sulla tua distribuzione, imposta un singolo ID Measurement di Google Analytics 4:
NEXT_PUBLIC_GA_ID=G-XXXXXXXXXX
È una variabile build-time del frontend, quindi impostala nell'ambiente di build del frontend (una variabile d'ambiente Vercel/host, o frontend/.env.local per una npm run build locale). Quando è impostata, GA viene caricata solo nelle build di produzione e traccia le visualizzazioni di pagina più alcuni eventi di prodotto (es. scan_started, scan_completed, report_downloaded). Gli eventi personalizzati passano attraverso l'helper tipizzato in frontend/lib/analytics.ts - trackEvent('scan_started').
Privacy: vengono inviati solo eventi di utilizzo anonimi e a bassa cardinalità - mai domini scansionati, risultati di scansione, findings, contenuti dei report, stato di autorizzazione o dati personali. Lascia NEXT_PUBLIC_GA_ID non impostato e ONUS si comporta esattamente come prima; l'analitica è interamente opt-in.
FastAPI genera automaticamente la documentazione Swagger interattiva - una volta che il backend è in esecuzione, apri http://localhost:8000/docs.
docker compose down
docker compose logs -f backend worker
pip install -r backend/requirements-dev.txt
pytest backend/tests
655 test automatici del backend al momento della scrittura. Oltre alla suite unit/integrazione, lo strumento è stato esercitato end-to-end durante lo sviluppo: 79 scansioni reali eseguite e 124 report PDF generati contro nove applicazioni di pratica deliberatamente vulnerabili (DVWA, Juice Shop, Mutillidae, NodeGoat, bWAPP, WebGoat, Metasploitable2, DVWP/WordPress dietro un WAF) più un target pubblico autorizzato (testphp.vulnweb.com) - non numeri ipotetici. Scansiona solo target che sei esplicitamente autorizzato a testare - vedi docs/test_findings.md per i target di pratica usati durante lo sviluppo.
ARCHITECTURE.md - architettura completa, schemi e i contratti che una modifica non dovrebbe mai rompere. Leggilo prima di fare una modifica non banale.docs/QUICK_REF.md - comandi di esecuzione, responsabilità delle cartelle, "dove faccio questa modifica".docs/scanners.md - ragionamento dietro il design di timing/flag di ogni modulo di scansione.docs/ai.md - ottimizzazione di timeout/contesto di Ollama, perché la valutazione è stata rimossa completamente dall'LLM.docs/docker.md - note sulle deviazioni Docker e problemi di build.docs/troubleshooting.md - come testare manualmente ogni modulo/fase in isolamento.docs/roadmap.md - sequenza storica di build (la build è completa).MIT - vedi LICENSE.
Scansionare target senza esplicita autorizzazione scritta è illegale ai sensi dell'IT Act 2000 (India) e degli statuti internazionali equivalenti. Questo strumento richiede la conferma di autorizzazione a ogni scansione e registra operatore + timestamp per responsabilità.
| Self-hosted (questo repository) | Hosted (tryonus.tech) |
|---|
| Setup | docker compose up | nessuno - basta aprire il sito |
| Accesso | nessuno - monoperatore | account / Google / GitHub OAuth |
| Flusso di scansione | dominio → casella di autorizzazione → scansione | uguale, dopo l'accesso |
| Extra | - | coda di scansione, cronologia per utente, email gestita |
| Esecuzione | sulla tua rete, air-gapped | cloud gestito |
| Variabile | Default | Scopo |
|---|
POSTGRES_PASSWORD | vapt_secure_2025 | Password del database |
SECRET_KEY | change_me_to_a_long_random_string | Chiave segreta del backend |
ALLOWED_HOSTS | localhost,127.0.0.1 | Host consentiti FastAPI |
OLLAMA_URL | http://host.docker.internal:11434 | Dove backend/worker raggiungono Ollama |
SCAN_TIMEOUT_MULTIPLIER | 1.5 | Scala i timeout tool/Celery di ogni modulo - i target del mondo reale sono più lenti di quelli di laboratorio; imposta 1.0 per tempi calibrati sul laboratorio |
MAX_CONCURRENT_SCANS | 3 | Limite di scansioni concorrenti (protezione da esaurimento risorse / cortesia verso il target; dimensiona anche il pool di connessioni DB) |
ONUS_ENV | development | development (localhost self-hosted - i segreti deboli generano solo un avviso) o production (SECRET_KEY/password Postgres deboli diventano un errore di avvio bloccante) |
CONTRIBUTING.md