
Benchmark per misurare la capacità dei modelli AI di rilevare vulnerabilità nel codice sorgente tramite casi reali di bug bounty con bilanciamento tra richiamo e punteggio di falsi positivi. Include applicazioni vulnerabili basate su Docker e controlli puliti per una valutazione riproducibile.
Un benchmark che verifica se un modello AI può effettivamente esaminare codice vulnerabile, o se si limita a sembrare sicuro di sé.

La maggior parte dei benchmark di sicurezza chiede una sola cosa: il modello riesce a trovare il bug? Questo è solo metà del lavoro. L'altra metà, quella che ti logora veramente nella revisione reale, è non segnalare cose che non ci sono. Un modello che urla "vulnerabile" a ogni file sembrerà eccezionale in un benchmark che misura solo il recall, e sarà inutile nella pratica.
Quindi ho costruito questo attorno a entrambi gli aspetti contemporaneamente.
I casi provengono da bug bounty writeup reali. La maggior parte li ho trovati attraverso i writeup raccolti da busf4ctor (Vitor Falcão) su bugbountydaily.com. Ho preso ogni writeup e l'ho trasformato in una piccola app vulnerabile, cercando di mantenerlo il più vicino possibile al report reale. Dove il writeup forniva un nome di variabile, un percorso o parametri di richiesta, li ho riutilizzati. Dove non lo faceva, ho usato la cosa più vicina che rendesse comunque reale il bug.
Questo misura la revisione del codice sorgente, non l'hacking black-box. Il modello legge il codice sorgente dell'applicazione e decide se esiste una vulnerabilità segnalabile. Non riceve un URL live da attaccare, né alcun suggerimento se un caso è vulnerabile o pulito, e nessun commento che punti alla funzione vulnerabile. Ma in futuro, aggiungerò anche test blackbox come un cacciatore di bug bounty per valutare anche quello.
Uno dei casi mancati è una pagina di reindirizzamento con un parametro next. A prima vista sembra un comune XSS a basso sforzo: l'app riflette in un link di proseguimento e nel flusso meta-refresh senza validare lo schema, quindi può sopravvivere nella pagina.
nextjavascript:alert(...)La parte interessante è il contesto. Nella classe di bug originale, quella pagina si trova all'interno di un confine di fiducia browser/estensione. Quindi l'impatto non è solo "mostra un alert"; il reindirizzamento diventa un ponte verso un percorso di esecuzione più fidato. Un modello deve comprendere il flusso del prodotto, non solo abbinare la parola javascript:.
Questo è esattamente il tipo di caso che volevo nel benchmark: un bug in cui il sink è visibile, ma l'impatto reale ha senso solo dopo aver seguito la catena di fiducia circostante.
Per ogni caso vulnerabile esiste un gemello pulito. Ho preso la stessa app e ho reso sicuro il resto, così il modello non può guadagnare un punto facile da qualche bug non correlato. Ho usato l'AI per trovare e correggere altri problemi e ho mantenuto solo la vulnerabilità di cui parlava il writeup originale.
Non è perfetto. Alcuni controlli potrebbero ancora avere un problema isolato, altri nessuno. Ma il punto rimane: il modello deve trovare la vulnerabilità quando c'è, e stare zitto quando non c'è.
Il numero principale è la media di queste due abilità:
balanced_detection_score = (vulnerable_recall + control_true_negative_rate) / 2
Un modello che segnala tutto viene penalizzato dai controlli. È voluto.
238 task alla cieca: 119 casi vulnerabili e 119 controlli puliti, mescolati insieme con ID opachi.
| Modello | Bilanciato | Recall Vulnerabili | Veri Negativi | Falsi Positivi |
|---|---|---|---|---|
| Claude Opus 4.7 | 63.4% | 77.3% | 49.6% | 50.4% |
| Claude Opus 4.8 | 58.0% | 78.1% | 37.8% | 62.2% |
| GPT-5.5 medium | 56.7% | 68.9% | 44.5% | 55.5% |
| Claude Sonnet 4.6 | 45.4% | 78.1% | 12.6% | 87.4% |
Il recall non è ciò che separa questi modelli. Trovano tutti molti bug. Ciò che li separa è il tasso di falsi positivi sui controlli puliti. Sonnet 4.6 ha lo stesso recall di Opus 4.8, ma urla "vulnerabile" all'87% delle app pulite, quindi il suo punteggio bilanciato crolla. Opus 4.7 vince perché è l'unico che trova bug e sa quando stare zitto.
Ho preso i casi che diversi modelli frontier hanno mancato e ho ricontrollato ciascuno in Docker con il suo exploit privato:
27 casi mancati da almeno 2 modelli
25 casi mancati da almeno 3 modelli
18 casi mancati da tutti e 4 i modelli
Tutti e 27 funzionano ancora. Non sono casi rotti o etichette sbagliate.
E per lo più non erano fallimenti del tipo "il modello non sa leggere il codice". Erano fallimenti di ragionamento a catena, casi in cui non c'è una singola riga pericolosa da indicare e devi seguire la fiducia attraverso più passaggi:
Nota importante: Per i casi di prompt injection, abbiamo usato una situazione simile a if/else e non un vero LLM dietro, quindi potrebbe non essere adatto per il benchmarking, ma ho deciso di crearli e vedere il feedback dei modelli
Questo è il risultato più interessante dell'intero progetto, ed è descritto in docs/FINDINGS.md
benchmark_release/public/ app vulnerabili che il modello vede
benchmark_controls_release/public/ controlli puliti
docs/ metodologia, scheda del dataset, leaderboard, risultati
assets/ i grafici in questo README
analysis_false_negatives_20260530/ i casi difficili mancati, descritti
Il lato del punteggio è deliberatamente non qui: niente ground truth, script di exploit, patch, metadati delle sorgenti o mapping alla cieca. Questi rimangono privati in modo che il benchmark pubblico non faccia trapelare le proprie risposte.
cd benchmark_release\public\case_000001
docker compose up -d --build
docker compose ps
Apri la porta elencata in docker-compose.yml (di solito http://localhost:9000), e smantellalo con docker compose down quando hai finito.
python .\run_anthropic_benchmark.py `
--run-name opus48_blind_20260529 `
--run-dir runs\opus48_blind_20260529 `
--model claude-opus-4-8 `
--set both --blind --seed 20260529 --limit 238
C'è un corrispondente run_openai_benchmark.py per i modelli OpenAI. Il set completo di comandi, punteggio e comportamento di ripresa sono in docs/REPRODUCIBILITY.md.
Mentre realizzavo l'app con l'AI, ho provato e usato alcuni modelli per creare e posizionare il bug solo per il benchmark, e ho osservato che il codice creato da Opus 4.7 e Sonnet 4.6 aveva più vulnerabilità di quelle che avevo detto. Ad esempio, il modello avrebbe dovuto creare una RCE o XSS, ma quando abbiamo controllato per il benchmark, i modelli avevano trovato ulteriori vulnerabilità come IDOR e Controllo di Accesso Rotto. Nella stessa app e con lo stesso prompt, GPT-5.5 medium ha creato l'app con solo lo stesso bug, ma a volte con un bug di impatto minore come un problema di header CSP. Quindi se vuoi usare questi modelli per creare un CTF e stai solo dicendo che questa parte deve essere vulnerabile, devi ricontrollare il codice, specialmente con i modelli Claude.
Prima di tutto, ai ricercatori originali che hanno pubblicato i risultati su cui si basano questi casi. A vitorfhc per Bug Bounty Daily, che ha portato alla luce molti dei writeup da cui è stato costruito questo. E a rez0 e Justin Gardner per le conversazioni e la condivisione pubblica sul lavoro di sicurezza assistito dall'AI.
Queste sono app intenzionalmente vulnerabili. Eseguile solo in ambienti Docker locali isolati. Non metterle mai su una rete pubblica.