Tag 3 · ca. 105 Minuten
Gate heißt: etwas ist objektiv grün oder rot — und der Agent kommt nicht daran vorbei, nur weil er sich sicher fühlt.
Tests schreiben lassen — und eigenes Testing-Tooling bauen
Der Agent braucht ein objektives Signal
Gefährliche Muster systematisch finden
Vom Happy Path zum Missbrauchsfall
Wo Daten das System betreten
Wer bist du — und was darfst du sehen
Das Risiko, das man nicht selbst geschrieben hat
Den Agenten angreifen lassen statt verteidigen
Mehrere Blickwinkel schlagen mehr Runden
Aus einmalig wird wiederkehrend
Wirkungs- und Schadensradius begrenzen
Aus Modul 1: das Modell ist nicht-deterministisch und klingt bei „weiß ich sicher" genauso souverän wie bei „klingt plausibel". Aus Modul 4: brauchbar wird das erst mit Verifiable Outputs.
Der Agent hört auf, wenn der Code plausibel aussieht.
Sein Abbruchkriterium ist sein eigenes Urteil — also genau das, was wir nicht prüfen können.
Der Agent hört auf, wenn der Test grün ist.
Sein Abbruchkriterium liegt außerhalb von ihm — und ihr könnt es in einer Zeile nachprüfen.
Testgerüst und Boilerplate, Randfälle aufzählen, Parametrisierung, Tests für ungetesteten Altcode nachrüsten, Testdaten erzeugen.
Entscheiden, was fachlich richtig ist. Ein Test, den der Agent aus dem Code ableitet, zementiert den Bug, statt ihn zu finden.
Gegenmittel: das erwartete Ergebnis kommt vom Menschen, die Ausformulierung vom Agenten. Bei Bugfixes: erst der rote Test, der den Fehler zeigt — erst dann der Fix.
aus cgsit-finance/docs/testing.md — Pflichtsicht vor jedem neuen Test
| Layer | Test-Typ | DB | Daten-Quelle |
|---|---|---|---|
| L1 | Unit | keine (Mockito) | Inline + mock() |
| L2 | Integration (@QuarkusTest) | Testcontainer (DevServices) | per-test Factory-Bean |
| L3 | E2E (Playwright) | lokale bzw. CI-Postgres | Seed-Katalog + Test-User-Fixture |
price_eur. Bei
EUR-Listings ist genau diese Spalte null — der Wert steht
in price. Ergebnis: leere Kurve in Produktion.
Der Unit-Test war grün, weil das Mock
getPriceEur() stubte.
Lehre: Mocks bilden die Form der DB-Zeile nicht ab. Grün auf L1 heißt nur „die Rechnung stimmt", nicht „die Daten sehen so aus".
| Layer | fängt | fängt NICHT |
|---|---|---|
| L1 Unit | Rechenlogik, Branches, Randfälle | Zeilenform, SQL-Semantik, Wire-Vertrag, Auth |
| L2 Integration | DB-Form, null-Spalten, Mapping, echtes SQL | Naht Frontend↔REST: DTO-Form, Datumsformat, JWT |
| L3 E2E | Vertrag über den Draht, Routing, Auth-Header | reine Rechen-Korrektheit (macht L1 billiger) |
Decision-Matrix aus cgsit-finance/docs/testing.md — verhindert die Klasse „Test fällt nur in CI um"
| Symptom / Bedarf | Wohin die Daten gehören |
|---|---|
| Test fällt nur lokal um, in CI grün | Test hängt an lokalem Zustand → Seed-Katalog oder Factory nutzen |
| Test fällt nur in CI um, lokal grün | Test hängt an dev-only Seed → self-contained machen |
| Neue allgemein bekannte Stammdaten | in die zentrale Seed-Datei → landet damit auch in CI |
| Ein Datensatz für genau einen Test | Test-Factory / Fixture-API, nicht der globale Seed |
| Reine Service-Logik prüfen | L1 — kein Quarkus, keine DB, Mockito |
| SQL / Mapping prüfen | L2 — Factory injizieren, nichts über die DB annehmen |
„Der Agent soll Tests laufen lassen" heißt praktisch: ihr baut ihm den Knopf, den er drückt — und entscheidet, was von der Ausgabe in den Context kommt.
Ein voller Maven-Log frisst mehr Context als die Aufgabe. Nur Fehlschläge und Zusammenfassung zurückgeben.
Der lärmende Teil passiert in einem eigenen Context; zurück kommt das Ergebnis, nicht das Protokoll.
Einzelner Test statt ganze Suite in der Iterationsschleife — Vollauf erst am Gate.
Namensschema, AAA-Struktur, „keine CSS-Selektoren in E2E" — als Regel im Repo, nicht als Chatnachricht.
Er findet Schwachstellen im eigenen Code: riskante Muster, fehlende Input-Validierung, löchrige AuthN/AuthZ, veraltete Abhängigkeiten, gefährliche Konfiguration.
Frage: Wie mache ich mein System härter?
Er führt Befehle aus, hat Schreibzugriff aufs Repo, Zugang zu Secrets in der Umgebung — und liest Text, den er nicht geschrieben hat: Issues, Webseiten, fremde Repos.
Frage: Was passiert im schlimmsten Fall — und wie klein kann ich das machen?
Der Agent ist gut darin, Muster über viele Dateien zu finden — und genau so beschreibt man Sicherheitsprobleme.
Jede Query, die aus "..." + variable entsteht.
Leerer catch-Block: der Fehler passiert, niemand erfährt davon.
Passwörter, Tokens, Connection-Strings als Literal.
Query ohne Einschränkung auf den eingeloggten Kontext.
Grenzwerte und Limits ohne Namen — niemand weiß, ob sie noch gelten.
Dateiname aus Nutzereingabe direkt im Dateisystem.
„Als Nutzer möchte ich meine Buchung stornieren."
Testet, dass das System das Erlaubte kann.
„Als Nutzer storniere ich die Buchung eines anderen, indem ich die ID in der URL hochzähle."
Testet, dass das System das Verbotene verweigert.
Sinnvolle Sammelfragen an den Agenten: Was passiert bei fremder ID? Bei negativer Menge? Bei doppeltem Absenden? Bei abgelaufenem Token? Bei 0 Byte und bei 500 MB?
Die Leitfrage lautet nicht „ist das gültig?", sondern: wo genau betritt fremde Eingabe das System — und was passiert dort mit ihr?
findByEmail — sonst entstehen „doppelte" Datensätze, die nie zusammenfinden.Token-Signatur wirklich geprüft? Ablauf beachtet? Secrets aus der Umgebung statt aus dem Quelltext? Passwort-Hashing zeitgemäß? Reset-Token einmalig und kurzlebig?
Wird die Identität aus dem Token gezogen — oder aus dem Pfad? Filtert die Query wirklich? Gibt es einen Endpunkt ohne Prüfung, weil er „intern" ist?
Bekannte Schwachstellen in Bibliotheken und Basis-Images — Code, den ihr nie geschrieben und nie gelesen habt.
Ein einmal committetes Passwort bleibt in der Historie, auch wenn die Datei „aufgeräumt" wurde.
Test- und Debug-Flags, die in Produktion versehentlich aktiv sind.
Was lokal an ist und in Produktion aus sein muss — und wer das prüft.
Ein Review-Auftrag wird brauchbar, wenn er drei Dinge mitbringt: einen Auslöser, eine Messlatte und ein festes Ausgabeformat.
datei:zeile, Begründung und Fixvorschlag — plus eine Empfehlung am Ende.Standardaufträge lassen den Agenten verteidigen. Dabei bestätigt er gern, dass alles in Ordnung ist. Dreht die Rolle um: er soll das eigene System angreifen.
Ein Reviewer, dreimal gefragt: „Ist der Code okay?"
Ergebnis: dreimal dieselbe blinde Stelle — nur selbstbewusster formuliert.
Mehrere Reviewer mit unterschiedlichem Auftrag, jeder mit eigener Messlatte und frischem Context.
Ergebnis: Befunde, die sich nicht überlappen.
Der Reviewer sieht den Diff, nicht die Entstehungsgeschichte. Kein „das haben wir doch besprochen".
Nicht „prüf das nochmal", sondern eine eigene Rolle mit eigener Checkliste.
Invarianten aus dem Repo — nicht die Meinung des Reviewers.
Der Agent priorisiert Befunde. Ob ein Risiko akzeptabel ist, entscheidet ihr.
Und die Umkehrung: Ein Review-Report ist ein Vorschlag, kein Prüfergebnis. Jeder Befund wird am Code verifiziert — auch die, die überzeugend klingen. Besonders die.
Die drei Fragen, die man einmal pro Projekt beantwortet:
Echte deny-Liste aus cgsit-finance/.claude/settings.json
| Kategorie | Beispiele | Warum unumkehrbar |
|---|---|---|
| Dateisystem | rm -rf / | kein Papierkorb, kein Git |
| Git-Historie | git push --force *, git reset --hard*, git clean -fd* | zerstört genau das Sicherheitsnetz, auf das man sich verlässt |
| Datenbank | *DROP TABLE*, *DROP DATABASE* | Daten weg, Wiederherstellung nur aus Backup |
| Container | docker compose down -v* | -v löscht das Volume — also die Datenbank |
| Cloud | aws ec2 terminate-instances*, aws rds delete-db-*, aws s3 rb*, aws iam delete-* | Ressourcen und Zugänge weg, teils sofort |
| Veröffentlichung | npm publish*, mvn deploy* | öffentlich ist öffentlich — auch nach dem Zurückziehen |
| Datenabfluss | *pastebin*, *transfer.sh*, *file.io* | Inhalte verlassen die Firma, unbemerkt und endgültig |
docker compose down ist lokal harmlos — die Entwicklungs-DB
ist Wegwerfware. Auf Produktion ist derselbe Befehl ein Vorfall. Ein pauschales
Verbot würde die tägliche Arbeit behindern und deshalb umgangen.
compose down, und es zielt auf Produktion (Prod-IP oder ssh).up -d --force-recreate oder stop/start.git commit, dessen
Commit-Text die Wörter „docker compose down" enthielt.
Lehre: Auch ein Wächter braucht Präzision. Zu grob heißt Fehlalarme, Fehlalarme heißen abgeschaltete Wächter.
Ein Agent verarbeitet Inhalte, die niemand aus eurem Team geschrieben hat: Issue-Beschreibungen, Kommentare in Pull Requests, abgerufene Webseiten, Dateien aus fremden Repositories, Log-Ausgaben von Dritten.
Für das Modell ist all das erst einmal Text im Context — also potenziell Anweisung. Das ist der Kern von Prompt Injection.
„Ich habe dem Agenten nichts Gefährliches gesagt."
Stimmt — aber gesagt hat es der Inhalt, den er auf eure Anweisung hin gelesen hat.
Fremdinhalte als Daten behandeln, nicht als Auftrag. Blast Radius klein halten. Unumkehrbares mit Freigabe. Und: schauen, was der Agent ausführen will, nicht nur dass er etwas will.
Alles bisher Gezeigte ist ohne Wiederholung eine Momentaufnahme. Ein Security-Review vom März sagt nichts über den Code vom Juli.
| Wann | Was läuft | Warum dort |
|---|---|---|
| Beim Schreiben (Hook) | Guardrails auf geänderte Dateien | sofortiges Feedback, bevor der Fehler wächst |
| Vor dem Commit | betroffene Tests, Review sensibler Bereiche | billigster Zeitpunkt für einen Fix |
| Bei jedem Push / PR | Build, Unit, Integration, E2E | die Instanz, die niemand überstimmt |
| Beim Image-Bau | Schwachstellen-Scan, Abbruch bei kritischen Funden | verhindert, dass Bekanntes in Produktion geht |
| Wöchentlich (Zeitplan) | Secret-Scan über die volle Historie | findet auch, was vor Monaten hineinrutschte |
Setzt einen Review-Loop auf examples/legacy-playground an
— unaufgeräumter, testfreier Java-Code mit SQL-String-Konkatenation,
verschluckten Exceptions, hartkodierten Zugangsdaten und magischen Zahlen.
datei:zeile, Kategorie, Begründung, Schweregrad.Dauer ca. 30 Minuten · Paararbeit · nur eigener Kurs-Code
Alle Rechte vorbehalten
Diese Schulungsunterlagen sind urheberrechtlich geschützt. Vervielfältigung, Weitergabe oder kommerzielle Nutzung — auch in Auszügen — nur mit ausdrücklicher schriftlicher Genehmigung der CGS IT Solutions GmbH.
cgsit-claude-training · Modul 9 · v0.1.0