Modul 9

Testing & AI Security im Workflow

Tag 3 · ca. 105 Minuten

Lernziel Modul 9

Der Teilnehmer kann Tests und Security-Checks als Gates in den Workflow und die CI einbauen und agentische Review-Loops aufsetzen.

Gate heißt: etwas ist objektiv grün oder rot — und der Agent kommt nicht daran vorbei, nur weil er sich sicher fühlt.

Inhalt

AI-assisted Testing

Tests schreiben lassen — und eigenes Testing-Tooling bauen

Closing the Loop

Der Agent braucht ein objektives Signal

Risky Code Pattern Discovery

Gefährliche Muster systematisch finden

Abuse Cases & Security Tests

Vom Happy Path zum Missbrauchsfall

Input Validation

Wo Daten das System betreten

AuthN & AuthZ Checks

Wer bist du — und was darfst du sehen

Dependency & Config Risks

Das Risiko, das man nicht selbst geschrieben hat

Security-Reviews & Red-Team

Den Agenten angreifen lassen statt verteidigen

Multi-Agent Review Loops

Mehrere Blickwinkel schlagen mehr Runden

Recurring Checks & CI

Aus einmalig wird wiederkehrend

Blast Radius

Wirkungs- und Schadensradius begrenzen

Teil A — Testing als Orakel für den Agenten

Ohne Signal rät der Agent

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.

Ohne Test

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.

Mit Test

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.

Ein Test ist für den Agenten kein Qualitätsdokument, sondern ein Orakel: die einzige Instanz im Raum, die nicht höflich ist.

Closing the Loop

Auftrag
Ändern
Test
ausführen
Rot?
Ziel!
Grün → fertig
  • Offener Loop: Der Mensch sagt nach jeder Runde, ob es passt. Teuer, langsam, ermüdend (→ Approval Fatigue, Modul 4).
  • Geschlossener Loop: Der Agent bekommt das Urteil vom Werkzeug und iteriert selbst, bis das Werkzeug schweigt.
Ein roter Test ist ein Geschenk. Er verwandelt „mach das gut" in eine Aufgabe mit Abbruchbedingung.

AI-assisted Testing — realistisch

Stark

Testgerüst und Boilerplate, Randfälle aufzählen, Parametrisierung, Tests für ungetesteten Altcode nachrüsten, Testdaten erzeugen.

Schwach

Entscheiden, was fachlich richtig ist. Ein Test, den der Agent aus dem Code ableitet, zementiert den Bug, statt ihn zu finden.

Der klassische Fehllauf: Der Test ist grün, weil der Agent ihn an das Ist-Verhalten angepasst hat — nicht an das Soll. Ein Test ohne fachliche Erwartung ist ein Screenshot.

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.

Das 3-Layer-Modell — echtes Beispiel

aus cgsit-finance/docs/testing.md — Pflichtsicht vor jedem neuen Test

LayerTest-TypDBDaten-Quelle
L1Unitkeine (Mockito)Inline + mock()
L2Integration (@QuarkusTest)Testcontainer (DevServices)per-test Factory-Bean
L3E2E (Playwright)lokale bzw. CI-PostgresSeed-Katalog + Test-User-Fixture
Jeder Layer hat eine andere Verantwortung und eine andere Datenquellen-Konvention. Mischen erzeugt fragile Tests — und fragile Tests sind für den Agenten ein lügendes Orakel.

Was ein Layer nicht fängt

Version 0.65.0 Ein Performance-Berechner las nur die Spalte 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".
Layerfängtfängt NICHT
L1 UnitRechenlogik, Branches, RandfälleZeilenform, SQL-Semantik, Wire-Vertrag, Auth
L2 IntegrationDB-Form, null-Spalten, Mapping, echtes SQLNaht Frontend↔REST: DTO-Form, Datumsformat, JWT
L3 E2EVertrag über den Draht, Routing, Auth-Headerreine Rechen-Korrektheit (macht L1 billiger)

Wo leben meine Testdaten?

Decision-Matrix aus cgsit-finance/docs/testing.md — verhindert die Klasse „Test fällt nur in CI um"

Symptom / BedarfWohin die Daten gehören
Test fällt nur lokal um, in CI grünTest hängt an lokalem Zustand → Seed-Katalog oder Factory nutzen
Test fällt nur in CI um, lokal grünTest hängt an dev-only Seed → self-contained machen
Neue allgemein bekannte Stammdatenin die zentrale Seed-Datei → landet damit auch in CI
Ein Datensatz für genau einen TestTest-Factory / Fixture-API, nicht der globale Seed
Reine Service-Logik prüfenL1 — kein Quarkus, keine DB, Mockito
SQL / Mapping prüfenL2 — Factory injizieren, nichts über die DB annehmen
Diese Matrix ist eine Entscheidung, die einmal jemand getroffen hat — im Repo steht sie dem Agenten bei jedem Test wieder zur Verfügung.

Custom Testing Tooling

„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.

Ausgabe eindampfen

Ein voller Maven-Log frisst mehr Context als die Aufgabe. Nur Fehlschläge und Zusammenfassung zurückgeben.

Im Subagenten laufen lassen

Der lärmende Teil passiert in einem eigenen Context; zurück kommt das Ergebnis, nicht das Protokoll.

Gezielt statt alles

Einzelner Test statt ganze Suite in der Iterationsschleife — Vollauf erst am Gate.

Konventionen mitliefern

Namensschema, AAA-Struktur, „keine CSS-Selektoren in E2E" — als Regel im Repo, nicht als Chatnachricht.

Ob dieses Tooling bei euch ein Skill, ein Command, ein Hook oder ein Make-Target wird, ist eine Frage der Werkzeugkiste aus Modul 2/8. Konkrete Konfigurations- schlüssel vor dem Kurs gegen die offizielle Dokumentation prüfen. — geprüft am 2026-07-21

Tests als Gate, nicht als Anhang

1Lokal, in der Schleife — der Agent iteriert gegen einen einzelnen Test, bis er grün ist.
Vor dem Commit Gate — betroffene Suite grün, sonst kein Commit. Hook oder Skill, nicht Disziplin.
Im Review Mensch — ist der Test fachlich richtig, oder zementiert er nur das Ist-Verhalten?
In der CI Gate — die Instanz, die niemand lokal überstimmen kann. Erst hier zählt grün wirklich.
Ein Gate, das man wegdiskutieren kann, ist kein Gate. Der Agent diskutiert nicht — aber ihr tut es, um 17:45 Uhr am Freitag.

Teil B — Security in zwei Richtungen

Zwei Bedeutungen, bitte nicht vermischen

1. Der Agent als Werkzeug

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?

2. Der Agent als Risiko

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?

Beide Richtungen brauchen Arbeit. Wer nur die linke Spalte betreibt, hat einen fleißigen Sicherheitsprüfer mit Produktionszugang.

Risky Code Pattern Discovery

Der Agent ist gut darin, Muster über viele Dateien zu finden — und genau so beschreibt man Sicherheitsprobleme.

SQL per String-Konkatenation

Jede Query, die aus "..." + variable entsteht.

Verschluckte Exceptions

Leerer catch-Block: der Fehler passiert, niemand erfährt davon.

Secrets im Code

Passwörter, Tokens, Connection-Strings als Literal.

Fehlender Mandantenfilter

Query ohne Einschränkung auf den eingeloggten Kontext.

Magische Zahlen

Grenzwerte und Limits ohne Namen — niemand weiß, ob sie noch gelten.

Ungeprüfte Pfade & Uploads

Dateiname aus Nutzereingabe direkt im Dateisystem.

Nützlich wird das erst als benannte Liste: Ein „schau mal, ob was unsicher ist" liefert Prosa. Eine Musterliste liefert Fundstellen mit Datei und Zeile.

Abuse Cases & Security Tests

Use Case

„Als Nutzer möchte ich meine Buchung stornieren."

Testet, dass das System das Erlaubte kann.

Abuse Case

„Als Nutzer storniere ich die Buchung eines anderen, indem ich die ID in der URL hochzähle."

Testet, dass das System das Verbotene verweigert.

Ein Abuse Case ist ein ganz normaler Test — nur mit umgekehrter Erwartung: nicht 200, sondern 403 oder 404. Damit wird Security zu etwas, das grün oder rot ist. Also zu einem Gate.

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?

Input Validation

Die Leitfrage lautet nicht „ist das gültig?", sondern: wo genau betritt fremde Eingabe das System — und was passiert dort mit ihr?

1Eintrittspunkte aufzählen lassen. REST-Parameter, Request-Body, Header, Upload, Import-Datei, Cron-Parameter, Webhook.
2Pro Eintrittspunkt prüfen: Typ, Wertebereich, Länge, Pflichtfeld — und ob die Prüfung serverseitig passiert. Frontend-Validierung ist Komfort, keine Sicherheit.
3Normalisieren vor dem Vergleich. E-Mail klein und getrimmt vor findByEmail — sonst entstehen „doppelte" Datensätze, die nie zusammenfinden.
4Ablehnen statt reparieren. Fehlt der Wechselkurs, wird nicht heimlich 1,0 angenommen — die Operation scheitert laut.

Authentication & Authorization

AuthN — wer bist du?

Token-Signatur wirklich geprüft? Ablauf beachtet? Secrets aus der Umgebung statt aus dem Quelltext? Passwort-Hashing zeitgemäß? Reset-Token einmalig und kurzlebig?

AuthZ — was darfst du sehen?

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?

Invariante Aus dem Review-Katalog von cgsit-finance: Jeder Endpunkt zieht die Mandanten-ID aus dem JWT, niemals aus dem Pfadparameter. Zugriff auf fremde Ressourcen antwortet mit 404, nicht 403. Warum 404: Ein 403 bestätigt, dass die Ressource existiert — damit lässt sich ihr Bestand durchprobieren.

Dependency & Configuration Risks

Abhängigkeiten

Bekannte Schwachstellen in Bibliotheken und Basis-Images — Code, den ihr nie geschrieben und nie gelesen habt.

Secrets im Repo

Ein einmal committetes Passwort bleibt in der Historie, auch wenn die Datei „aufgeräumt" wurde.

Gefährliche Schalter

Test- und Debug-Flags, die in Produktion versehentlich aktiv sind.

Drift zwischen Umgebungen

Was lokal an ist und in Produktion aus sein muss — und wer das prüft.

Praxis cgsit-finance Ein Schalter aktiviert Test-Endpunkte für E2E-Läufe. Er ist per Default aus, wird in CI gesetzt, ist in Produktion verboten — und ein eigener Test prüft genau das. Zusätzlich läuft ein Secret-Scanner über die volle Git-Historie und ein Image-Scanner bricht den Build bei kritischen Funden ab. Lehre: Konfiguration ist die erste Verteidigungslinie — und sie braucht einen Test, sonst ist sie nur eine Absichtserklärung.

Agentische Security-Reviews

Ein Review-Auftrag wird brauchbar, wenn er drei Dinge mitbringt: einen Auslöser, eine Messlatte und ein festes Ausgabeformat.

1Auslöser (sensibler Bereich): Geld, Auth, Mandantengrenze, Migration auf großer Tabelle. Nicht jede Änderung braucht ein Review — diese schon.
2Messlatte: die konkreten Invarianten des Bereichs plus die zu lesenden Dokumente. Ohne Messlatte misst der Agent gegen sein Bauchgefühl.
3Umfang: die geänderten Dateien, das Ziel der Änderung — nicht „das Projekt".
4Ausgabeformat: pro Befund Konform / Warnung / Verstoß, jeweils mit datei:zeile, Begründung und Fixvorschlag — plus eine Empfehlung am Ende.
Erzwungenes Format ist kein Formalismus: Es macht Befunde zählbar, abarbeitbar und überprüfbar — und verhindert den wohlwollenden Fließtext, in dem alles irgendwie in Ordnung ist.

Red-Team Prompts

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.

Red-Team 1 — Missbrauchsfälle als TestsYou are attacking OUR OWN service in examples/seminar-api. Goal: find ways an authenticated user can affect data that is not theirs. Enumerate every REST endpoint that takes an id, then for each one write a failing integration test that attempts the abuse (foreign id, replayed request, negative amount, expired token). Do not fix anything yet. Output: a table endpoint | abuse | expected status | test file, plus the tests themselves.
Red-Team 2 — Datenpfad rückwärtsTrace every path where untrusted input reaches a database query or the file system in examples/legacy-playground. Report file:line, the exact expression that concatenates input, and what an attacker controls at that point. Rank findings by exploitability. No fixes, no refactoring — findings only.
Red-Team 3 — Geheimnisse und KonfigurationAssume this repository will be published tomorrow. Find everything that must not be public: credentials, tokens, internal hostnames, debug flags that default to on. Check the git history too, not just the working tree. List each finding with file:line and the concrete blast radius if leaked.
Alle drei Prompts zielen ausschließlich auf eigene Systeme dieses Kurses. Angriffsaufträge gegen fremde Systeme sind weder Kursinhalt noch zulässig. — geprüft am 2026-07-21

Multi-Agent Review Loops

Dreimal dieselbe Frage

Ein Reviewer, dreimal gefragt: „Ist der Code okay?"

Ergebnis: dreimal dieselbe blinde Stelle — nur selbstbewusster formuliert.

Verschiedene Blickwinkel

Mehrere Reviewer mit unterschiedlichem Auftrag, jeder mit eigener Messlatte und frischem Context.

Ergebnis: Befunde, die sich nicht überlappen.

Beleg cgsit-finance Es gibt zwei Reviewer-Rollen mit getrennten Aufträgen: der architecture-reviewer prüft Struktur, Schichten und die Invarianten sensibler Bereiche — der ux-reviewer prüft ausschließlich, ob an der Kundenoberfläche nur fachlich definierte Begriffe auftauchen. Auslöser für die zweite Rolle: ein internes Zugriffs-Konzept war als Kennzahl in die Kundenoberfläche geleakt. Tests, CI und der Architektur-Reviewer waren alle grün — keiner von ihnen hatte diese Frage im Auftrag.

Ehrlich dazugesagt

Ein Agent, der seinen eigenen Code reviewt, findet systematisch weniger. Er kennt seine Begründung noch — und eine Begründung, die man kennt, klingt richtig.

Frischer Context

Der Reviewer sieht den Diff, nicht die Entstehungsgeschichte. Kein „das haben wir doch besprochen".

Anderer Auftrag

Nicht „prüf das nochmal", sondern eine eigene Rolle mit eigener Checkliste.

Externe Messlatte

Invarianten aus dem Repo — nicht die Meinung des Reviewers.

Mensch am Ende

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.

Wirkungs- & Schadensradius begrenzen

„Blast Radius"

Blast Radius = alles, was kaputtgehen kann, wenn ein Schritt des Agenten falsch ist. Nicht „wie wahrscheinlich" — sondern „wie weit reicht es".

Die drei Fragen, die man einmal pro Projekt beantwortet:

  • Was kann er erreichen? Repo, Dateisystem, Netzwerk, Datenbanken, Cloud-Konten, Deploy-Ziele.
  • Was davon ist nicht rückholbar? Ein gelöschtes Volume, ein Force-Push, eine gedroppte Tabelle, ein veröffentlichtes Paket.
  • Was davon merkt niemand? Daten, die den Rechner verlassen, sind der schlimmste Fall — es gibt kein Rückgängig und kein Log.
Faustregel: Umkehrbares darf der Agent, Unumkehrbares nicht. Git ist deshalb euer wichtigstes Sicherheitsnetz — solange niemand die Historie überschreiben kann.

Schadensbegrenzung durch Verbote

Echte deny-Liste aus cgsit-finance/.claude/settings.json

KategorieBeispieleWarum unumkehrbar
Dateisystemrm -rf /kein Papierkorb, kein Git
Git-Historiegit 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
Containerdocker compose down -v*-v löscht das Volume — also die Datenbank
Cloudaws ec2 terminate-instances*, aws rds delete-db-*, aws s3 rb*, aws iam delete-*Ressourcen und Zugänge weg, teils sofort
Veröffentlichungnpm 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

Chirurgisch verbieten, nicht pauschal lähmen

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.

1Ein Hook sieht den Befehl vor der Ausführung.
2Er blockt nur, wenn alle drei Bedingungen zutreffen: der Befehl wird wirklich ausgeführt (nicht nur in einem Commit-Text zitiert), es ist ein compose down, und es zielt auf Produktion (Prod-IP oder ssh).
Blockade mit Begründung und Alternative im Text: up -d --force-recreate oder stop/start.
4Bei einem Fehler im Hook selbst: durchlassen — ein kaputter Wächter darf nicht die ganze Arbeit blockieren.
2026-07-01 Die erste Fassung des Hooks blockte einen 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.

Der Agent liest fremden Text

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.

Die Denkfalle

„Ich habe dem Agenten nichts Gefährliches gesagt."

Stimmt — aber gesagt hat es der Inhalt, den er auf eure Anweisung hin gelesen hat.

Was hilft

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.

Deshalb ist die Antwort auf Approval Fatigue (Modul 4) nicht „alles erlauben", sondern: wenige, aber echte Entscheidungspunkte.

Recurring Checks & CI Integration

Alles bisher Gezeigte ist ohne Wiederholung eine Momentaufnahme. Ein Security-Review vom März sagt nichts über den Code vom Juli.

WannWas läuftWarum dort
Beim Schreiben (Hook)Guardrails auf geänderte Dateiensofortiges Feedback, bevor der Fehler wächst
Vor dem Commitbetroffene Tests, Review sensibler Bereichebilligster Zeitpunkt für einen Fix
Bei jedem Push / PRBuild, Unit, Integration, E2Edie Instanz, die niemand überstimmt
Beim Image-BauSchwachstellen-Scan, Abbruch bei kritischen Fundenverhindert, dass Bekanntes in Produktion geht
Wöchentlich (Zeitplan)Secret-Scan über die volle Historiefindet auch, was vor Monaten hineinrutschte
Der Übergang von einmalig zu wiederkehrend ist der eigentliche Wertschritt: Ein Fund wird zur Regel, eine Regel wird zum Gate, ein Gate wird zur Selbstverständlichkeit.

Modul 9 in fünf Sätzen

1Ohne objektives Signal rät der Agent — ein Test ist sein Orakel, ein roter Test sein Ziel.
2Das Soll kommt vom Menschen, die Ausformulierung vom Agenten. Sonst zementiert der Test den Bug.
3Security-Anforderungen werden erst zu Gates, wenn sie Tests sind: Abuse Cases, Validierung, AuthZ.
4Mehrere Reviewer mit verschiedenen Blickwinkeln schlagen einen Reviewer mit drei Anläufen — und jeder Befund wird am Code verifiziert.
5Der Agent ist auch ein Risiko: Blast Radius bewusst begrenzen — chirurgisch verbieten, nicht pauschal lähmen.
Testing und Security sind in diesem Kurs kein Qualitätsthema, sondern ein Steuerungsthema: Sie sind die einzigen Instanzen im Setup, die dem Agenten widersprechen können.

Übung 9 — Security-Review-Loop

Aufgabe

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.

  1. Erster Durchlauf: Befunde sammeln, keine Fixes. Festes Ausgabeformat verlangen: datei:zeile, Kategorie, Begründung, Schweregrad.
  2. Zweiter Durchlauf mit anderem Blickwinkel und frischer Session (z. B. Red-Team statt Review). Befunde zusammenführen.
  3. Jeden Befund einzeln am Code nachprüfen — öffnen, Zeile lesen, bestätigen oder verwerfen.
Verifizierbares Ergebnis: eine Befundliste, in der jeder Eintrag am Code verifiziert ist — mit Fundstelle und Urteil bestätigt / nicht zutreffend / unklar. Kein ungeprüfter Agenten-Report zählt. Nennt außerdem mindestens einen Befund, den nur einer der beiden Durchläufe gefunden hat.

Dauer ca. 30 Minuten · Paararbeit · nur eigener Kurs-Code

© 2026 CGS IT Solutions GmbH

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