TIPS 49 · QUATTRO

Es besteht die Tests, sicher ist es nicht

Der Prompt, den ich einer zweiten Claude-Code-Sitzung gebe, wenn die Tests grün sind: Ich bitte sie, den gerade geschriebenen Code anzugreifen, nicht ihn abzunicken, und bringe den Bericht zur ersten zurück.

Was es ist und warum es zählt

Wenn Claude Code eine Aufgabe beendet und dir „fertig, Tests bestanden“ sagt, wirkt das wie das Ende der Geschichte. Ist es nicht. Grüne Tests sagen dir nur eins: Der Code macht, was die Tests prüfen. Und die Tests prüfen, was verlangt wurde. Wenn du verlangt hast „lass mich eine Bestellung speichern“, prüft der Test, dass die Bestellung gespeichert wird. Niemand hat gefragt, was passiert, wenn jemand sie ohne Login speichert oder im Namen eines anderen Nutzers.

Deshalb heißt „besteht die Tests“ nicht „ist sicher“. Eine App kann alle ihre Tests bestehen und trotzdem einen Nutzer die Daten eines anderen lesen lassen, dieselbe Zahlung zweimal annehmen oder einen geheimen Schlüssel in dem Teil lassen, der im Browser läuft, wo ihn jeder lesen kann.

Das sagt auch eine Studie, die am 10. Oktober 2026 auf arXiv erschienen ist: „Last Secure Code Benchmark: Is the Code You Vibe Secure?“. Sie hat sechs der fortschrittlichsten Coding-Agenten getestet. Ihr Code besteht die Funktionstests bei 73,6 bis 91,3 % der Aufgaben, je nach Agent. Aber selbst der beste der sechs schreibt nur bei 25,1 % der Aufgaben Code, der funktioniert und sicher ist.

Dieselbe Sitzung noch einmal prüfen zu lassen, bringt wenig: Sie hat diesen Code gerade geschrieben und weiß, warum sie es so gemacht hat. Ich öffne stattdessen eine zweite Sitzung und gebe ihr eine klare Rolle, die des Angreifers. Sie weiß nichts darüber, wie der Code entstanden ist, sieht nur die Änderungen und hat eine Aufgabe: herausfinden, wie man sie kaputt macht. Ich frage sie nicht, ob der Code in Ordnung ist. Ich frage sie, wo er nachgibt.

Warum es zählt: Wenn du eine App baust, ohne Entwickler zu sein, siehst du diese Lücken nicht, wenn du den Code noch einmal liest. Und wenn niemand nach ihnen sucht, findet sie als Erster ein Nutzer.

1. Der Prompt für den Angreifer

Ich füge ihn so, wie er ist, in die zweite Sitzung ein, wenn die erste fertig ist und die Tests grün sind.

Der Prompt
Du bist ein Angreifer, kein freundlicher Reviewer. Dieser Code besteht die Tests: Das ist mir egal, die Tests prüfen nur, was verlangt wurde. Du hast nur eine Aufgabe: Finde heraus, wie man kaputt macht, was gerade gebaut wurde. Schau dir nur die Änderungen an: Führ git status und git diff HEAD aus (es zeigt auch die schon gestagten) und lies die neuen Dateien, die git status auflistet, vollständig (der Diff zeigt sie nicht). Such nach:
- wer sie aufrufen kann: was ohne Login passiert, mit dem Login eines anderen Nutzers, wenn man die Adresse direkt aufruft;
- falsche Daten: leere Felder, extrem lange Texte, seltsame Zeichen, negative Zahlen, falsche Typen, dieselbe Anfrage zweimal geschickt;
- Schlüssel im Klartext: Passwörter, Tokens oder geheime Schlüssel im Code, in den Logs, in Fehlermeldungen oder in dem Teil, der im Browser läuft;
- Berechtigungen: wer Daten lesen, ändern oder löschen kann, die nicht seine sind;
- Grenzfälle: leere Listen, langsames Netz, zwei Nutzer im selben Moment.
Schreib zu jedem Problem: wo (Datei und Zeile), wie ich es kaputt mache (die genauen Schritte), was passiert, Schweregrad (hoch, mittel, niedrig). Sortier vom schwersten an. Korrigier nichts und ändere keine Dateien: Ich will nur den Bericht.

Warum er so geschrieben ist, Zeile für Zeile.

  • „Du bist ein Angreifer, kein freundlicher Reviewer“: Ein freundlicher Reviewer versucht, den Code zu verstehen, und lässt ihn am Ende eher durchgehen. Ein Angreifer geht davon aus, dass es eine Lücke gibt, und sucht sie.
  • „Führ git status und git diff HEAD aus“: Ein einfaches git diff zeigt nur die Änderungen, die noch nicht gestagt sind, also noch nicht mit git add für den nächsten Commit vorgemerkt. git diff HEAD vergleicht alle mit dem letzten Commit, vorgemerkt oder nicht. Dateien, die git noch nicht verfolgt, tauchen aber auch dort nicht auf: git status listet sie auf, und deshalb liest der Reviewer sie vollständig.
  • „Wer sie aufrufen kann“: Eine Seite kann einen Button vor Leuten ohne Berechtigung verstecken, aber wenn die Adresse, die dieser Button aufruft, jedem antwortet, schützt der versteckte Button gar nichts. Deshalb verlangt der Prompt, die Adresse direkt aufzurufen.
  • „Wie ich es kaputt mache (die genauen Schritte)“: Mit den Schritten kannst du selbst prüfen, ob das Problem wirklich da ist, und sie nach der Korrektur wiederholen, um zu sehen, ob es weg ist. Ein „da könnte ein Risiko sein“ kannst du nicht prüfen.
  • „Korrigier nichts und ändere keine Dateien“: Wer angreift, meldet nur. Die Korrekturen macht die Sitzung, die den Code geschrieben hat, so weißt du immer, wer was geändert hat.

2. Wie ich ihn nutze

  1. Die erste Sitzung sagt „fertig, Tests bestanden“. Ich bitte sie nicht, sich noch einmal selbst zu prüfen.
  2. Ich öffne ein neues Terminal im selben Ordner und starte claude: eine neue Sitzung, die das Gespräch nicht gesehen hat.
  3. Ich füge den Prompt vor dem Commit ein, damit git status und git diff HEAD nur die gerade erledigte Arbeit zeigen. Wenn ich schon committet habe, nenne ich ihr die Dateien selbst.
  4. Ich bringe den Bericht zur ersten Sitzung und lasse korrigieren, angefangen beim hohen Schweregrad. Für jedes ernste Problem verlange ich auch einen Test, der es nachstellt, damit beim nächsten Mal der Test es prüft.

Vom Bericht zu den Korrekturen

Der ersten Sitzung gebe ich den Bericht mit diesem Prompt:

Der Prompt
Hier ist der Bericht einer anderen Sitzung, die versucht hat, deine Arbeit kaputt zu machen: [Bericht einfügen]. Fang mit den Problemen mit hohem Schweregrad an, eins nach dem anderen. Schreib für jedes zuerst einen Test, der es nachstellt, und prüf, dass er fehlschlägt, dann korrigier es und prüf, dass der Test besteht. Sag mir, was du geändert und wie du es geprüft hast. Die mit niedrigem Schweregrad fass nicht an: Über die entscheide ich.

Der Test, der vor der Korrektur fehlschlägt, ist das entscheidende Stück. Er zeigt dir, dass das Problem wirklich da war und nicht nur eine Idee des Reviewers. Und er bleibt im Projekt: Wenn eine spätere Änderung dieselbe Lücke wieder öffnet, wird dieser Test rot.

Wenn du sicher sein willst, dass sie nichts anfasst

Im Prompt steht, dass sie keine Dateien ändern soll, aber es bleibt eine Bitte. Wenn ich eine echte Sperre will, starte ich die zweite Sitzung im plan mode:

Die Zeile
claude --permission-mode plan

Im plan mode liest Claude Dateien und führt Befehle zum Erkunden aus, etwa git status und git diff HEAD, ändert aber den Code nicht, bis du einen Plan genehmigst. Wenn sie dir am Ende einen mit Korrekturen vorschlägt, genehmige ihn nicht: Der Bericht reicht. In einer schon offenen Sitzung wechselst du hinein, indem du Shift+Tab drückst, bis unten „plan mode on“ erscheint.

3. Nichts erklären

Dem Reviewer erkläre ich nicht, warum der Code so gebaut ist. Wenn du es ihm erklärst, gibt er dir am Ende recht.

Das gilt für jeden Satz, den du zum Prompt hinzufügst: „ich habe es so gemacht, weil …“, „der Teil ist provisorisch“, „den Login übernimmt schon ein anderer Teil der App“. Solche Sätze ziehen den Reviewer auf deine Seite, bevor er den Code überhaupt ansieht. Gib ihm die Änderungen und die Aufgabe, mehr nicht. Die Erklärungen brauchst du später, wenn du entscheidest, was du korrigierst.

Häufige Fehler

  • „Tests bestanden“ als „sicher“ lesen: Die Tests prüfen, was verlangt wurde, also mach jedes Mal, wenn du Login, Berechtigungen oder Daten anfasst, eine Runde mit dem Angreifer.
  • Dieselbe Sitzung ihren eigenen Code angreifen lassen: Öffne ein neues Terminal und starte claude, damit der Angreifer ihn nicht geschrieben hat.
  • Ihn nach dem Commit starten, ohne die Dateien zu nennen: git diff HEAD zeigt die gerade erledigte Arbeit nicht mehr, also nenn ihr selbst die Dateien, die sie ansehen soll.
  • Dem Angreifer erklären, warum der Code so gebaut ist: Gib ihm nur die Änderungen und die Aufgabe, sonst gibt er dir am Ende recht.
  • Ohne Test korrigieren: Lass für jedes ernste Problem zuerst einen Test schreiben, der es nachstellt, damit du es merkst, wenn es zurückkommt.
  • Alles korrigieren, was er findet: Fang beim hohen Schweregrad an und entscheide über die niedrigen selbst, sonst füllt sich der Code mit unnötigen Absicherungen.

Checkliste

  • Die Tests sind grün und die erste Sitzung ist fertig
  • Der Angreifer ist in einer neuen Sitzung
  • Keine Erklärungen zum Prompt hinzugefügt
  • Vor dem Commit oder mit den genannten Dateien
  • Jedes Problem hat Datei und Zeile, Schritte, Folge und Schweregrad
  • Jedes Problem mit hohem Schweregrad ist korrigiert und hat seinen Test

Häufige Fragen

Wenn die Tests nicht reichen, wofür sind sie dann da?

Sie sind sehr nützlich. Sie sagen dir, dass funktioniert, was du verlangt hast, und dass die nächste Änderung es nicht unbemerkt kaputt macht. Sie sagen dir nicht, was passiert, wenn jemand die App auf eine Art nutzt, die niemand verlangt hat. Beides arbeitet zusammen: Der Angreifer findet die Lücke, der Test hält sie geschlossen.

Gibt es keinen fertigen Befehl für die Sicherheit?

Ja. /security-review untersucht die Änderungen auf deinem Branch nach Sicherheitslücken: Er vergleicht sie mit dem Hauptbranch des Remote-Repositorys, das Projekt braucht also eins, zum Beispiel auf GitHub. /code-review sucht dagegen nach Bugs in deinen aktuellen Änderungen. Der Prompt deckt aber auch Dinge ab, die nicht nur Sicherheit sind, etwa falsche Daten und Grenzfälle, und gibt dir die Schritte, um jedes Problem nachzustellen.

Wann lohnt es sich?

Wenn die Änderung Login, Berechtigungen, Nutzerdaten oder Zahlungen betrifft oder eine Adresse hinzufügt, die die App aus dem Browser aufruft. Dort trifft eine Lücke die Leute, die die App nutzen. Für einen Text oder eine Farbe braucht es das nicht.

← Alle Anleitungen