
Benchmark, der die Fähigkeit von KI-Modellen misst, Schwachstellen im Quellcode anhand realer Bug-Bounty-Fälle zu erkennen, mit ausgewogener Bewertung von Recall und False Positives. Enthält Docker-basierte verwundbare Anwendungen und saubere Kontrollen für eine reproduzierbare Bewertung.
Ein Benchmark, der prüft, ob ein KI-Modell wirklich verwundbaren Code reviewen kann – oder nur selbstsicher klingt.

Die meisten Sicherheits-Benchmarks stellen eine Frage: Findet das Modell den Bug? Das ist nur die halbe Arbeit. Die andere Hälfte – der Teil, der einen in der echten Review-Arbeit tatsächlich aufreibt – ist, keine Dinge zu melden, die gar nicht da sind. Ein Modell, das bei jeder Datei „verwundbar“ schreit, schneidet in einem Benchmark, der nur Recall misst, großartig ab – und ist in der Praxis nutzlos.
Also habe ich das Ganze um beide Seiten gleichzeitig herum gebaut.
Die Fälle stammen aus echten Bug-Bounty-Writeups. Die meisten davon habe ich über die von busf4ctor (Vitor Falcão) auf bugbountydaily.com gesammelten Writeups gefunden. Ich habe jedes Writeup genommen und daraus wieder eine kleine verwundbare App gemacht, wobei ich so nah wie möglich am echten Report bleiben wollte. Wo das Writeup einen Variablennamen, einen Pfad oder Request-Parameter angab, habe ich diese wiederverwendet. Wo nicht, habe ich das Nächstliegende verwendet, das den Bug trotzdem real machte.
Das misst Source-Code-Review, kein Black-Box-Hacking. Das Modell liest den Anwendungsquellcode und entscheidet, ob es eine meldenswerte Schwachstelle gibt. Es bekommt keine Live-URL zum Angreifen, keinerlei Hinweis darauf, ob ein Fall verwundbar oder sauber ist, und keinen Kommentar, der auf die verwundbare Funktion zeigt. Aber in Zukunft werde ich auch Blackbox-Tests als Bug-Bounty-Jäger hinzufügen, um das ebenfalls zu bewerten.
Einer der übersehenen Fälle ist eine Weiterleitungsseite mit einem next-Parameter. Auf den ersten Blick sieht das wie ein typisches Low-Effort-XSS aus: Die App spiegelt next in einen „Continue“-Link und einen Meta-Refresh-Flow, ohne das Schema zu validieren, sodass javascript:alert(...) in der Seite überleben kann.
Das Interessante ist der Kontext. In der ursprünglichen Bug-Klasse liegt diese Seite innerhalb einer Browser-/Erweiterungs-Vertrauensgrenze. Die Auswirkung ist also nicht nur „Popup mit Alert“; die Weiterleitung wird zu einer Brücke in einen stärker vertrauenswürdigen Ausführungspfad. Ein Modell muss den Produktfluss verstehen, nicht nur das Wort javascript: abgleichen.
Genau so einen Fall wollte ich in dem Benchmark haben: einen Bug, bei dem der Sink sichtbar ist, die tatsächliche Auswirkung aber erst nachvollziehbar wird, wenn man der umgebenden Vertrauenskette folgt.
Für jeden verwundbaren Fall gibt es einen sauberen Zwilling. Ich habe dieselbe App genommen und den Rest davon sicher gemacht, damit das Modell keinen einfachen Punkt durch einen unzusammenhängenden Bug bekommt. Ich habe KI eingesetzt, um andere Probleme zu finden und zu beheben, und nur die eine Schwachstelle behalten, um die es im ursprünglichen Writeup ging.
Das ist nicht perfekt. Manche Kontrollen könnten noch einen vereinzelten Fehler haben, manche gar keinen. Aber der Punkt bleibt: Das Modell muss die Schwachstelle finden, wenn sie da ist, und still sein, wenn sie nicht da ist.
Die Kennzahl an der Spitze ist der Durchschnitt dieser beiden Fähigkeiten:
balanced_detection_score = (vulnerable_recall + control_true_negative_rate) / 2
Ein Modell, das alles markiert, wird von den Kontrollen bestraft. Das ist Absicht.
238 blinde Aufgaben: 119 verwundbare Fälle und 119 saubere Kontrollen, gemischt mit undurchsichtigen IDs.
Der Recall ist es nicht, was diese Modelle voneinander trennt. Sie alle finden viele Bugs. Was sie trennt, ist die False-Positive-Rate bei sauberen Kontrollen. Sonnet 4.6 hat denselben Recall wie Opus 4.8, schreit aber bei 87 % der sauberen Apps „verwundbar“, wodurch sein ausgewogener Score einbricht. Opus 4.7 gewinnt, weil es das einzige ist, das sowohl Bugs findet als auch weiß, wann es still bleiben muss.
Ich habe die Fälle herausgezogen, die mehrere Frontier-Modelle übersehen haben, und jeden einzelnen in Docker mit seinem privaten Exploit erneut geprüft:
27 Fälle, die von mindestens 2 Modellen übersehen wurden
25 Fälle, die von mindestens 3 Modellen übersehen wurden
18 Fälle, die von allen 4 Modellen übersehen wurden
Alle 27 feuern immer noch. Das sind keine kaputten Fälle oder falschen Labels.
Und es waren größtenteils keine „Das Modell kann keinen Code lesen“-Fehler. Es waren Ketten-Schlussfolgerungs-Fehler – Fälle, in denen es keine einzelne gefährliche Zeile gibt, auf die man zeigen kann, und man Vertrauen über mehrere Schritte hinweg verfolgen muss:
Wichtiger Hinweis: Bei den Prompt-Injection-Fällen haben wir eine If/Else-Situation verwendet und keine echte LLM dahinter, das ist also vielleicht nicht ideal fürs Benchmarking, aber ich habe mich entschieden, sie zu erstellen und das Feedback der Modelle abzuwarten.
Das ist das interessanteste Ergebnis des gesamten Projekts und ist in docs/FINDINGS.md ausführlich beschrieben.
benchmark_release/public/ verwundbare Apps, die das Modell sieht
benchmark_controls_release/public/ saubere Kontrollen
docs/ Methodik, Dataset-Karte, Leaderboard, Erkenntnisse
assets/ die Diagramme in dieser README
analysis_false_negatives_20260530/ die schwierigen übersehenen Fälle, aufgeschrieben
Die Bewertungsseite ist absichtlich nicht dabei: keine Ground Truth, Exploit-Skripte, Patches, Quell-Metadaten oder Blind-Zuordnungen. Die bleiben privat, damit der öffentliche Benchmark seine eigenen Antworten nicht preisgibt.
cd benchmark_release\public\case_000001
docker compose up -d --build
docker compose ps
Öffne den in docker-compose.yml angegebenen Port (normalerweise http://localhost:9000) und fahre ihn mit docker compose down wieder herunter, wenn du fertig bist.
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
Für OpenAI-Modelle gibt es ein passendes run_openai_benchmark.py. Den vollständigen Befehlsatz, die Bewertung und das Fortsetzungsverhalten findest du in docs/REPRODUCIBILITY.md.
Während ich die App mit KI erstellt habe, habe ich einige Modelle nur für das Erstellen und Platzieren des Bugs im Benchmark ausprobiert und eingesetzt. Dabei habe ich beobachtet, dass Code, der von Opus 4.7 und Sonnet 4.6 erstellt wurde, mehr Schwachstellen enthielt als nur die, die ich genannt hatte. Das Modell sollte zum Beispiel ein RCE oder XSS erzeugen, aber als wir für den Benchmark prüften, hatten die Modelle mehr Schwachstellen gefunden, etwa IDOR und Broken Access Control. In derselben App und mit demselben Prompt erstellte GPT-5.5 medium die App nur mit demselben Bug, manchmal aber mit einem Bug mit geringerer Auswirkung, wie etwa einem CSP-Header-Problem. Wenn du diese Modelle also zum Erstellen einer CTF nutzen willst und nur sagst, dieser Teil muss verwundbar sein, musst du den Code doppelt prüfen, besonders bei Claude-Modellen.
Zuerst an die ursprünglichen Forscher, die die Erkenntnisse veröffentlicht haben, auf denen diese Fälle basieren. An vitorfhc für Bug Bounty Daily, der viele der Writeups zugänglich gemacht hat, aus denen das hier aufgebaut wurde. Und an rez0 und Justin Gardner für die Gespräche und das öffentliche Teilen rund um KI-gestützte Sicherheitsarbeit.
Das sind absichtlich verwundbare Apps. Führe sie nur in isolierten lokalen Docker-Umgebungen aus. Bringe sie niemals in ein öffentliches Netzwerk.
| Modell | Ausgewogen | Verwundbar-Recall | Richtig negativ | Falsch positiv |
|---|
| 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 % |