Workshop-Anwendung fuer eine Red-Team-vs-Blue-Team-Uebung zum Thema CyberSecurity im AI-Umfeld.
SecAssist ist ein interner Security-/Incident-Triage-Chatbot, der bewusst realistische, absichtlich eingebaute Schwachstellen enthaelt. Die Anwendung ist klein gehalten, browserfreundlich und auf reproduzierbare Workshop-Demos ausgelegt.
Berechtigung vor Kontext.
- Zuerst Actor bestimmen (Rolle)
- Dann Zweck / Aktion bestimmen
- Dann erlaubte Quellen bestimmen
- Dann Kontext aufbauen
- Erst am Schluss Text generieren oder einen Tool-Vorschlag verarbeiten
Sicherheitskritische Entscheidungen liegen in der PolicyEngine, im RetrievalService und im ToolPolicyService – nicht im LLM.
Die aktuelle App-Version bietet:
- Rollenwahl im Browser (
employee,security_analyst,contractor) - separate Falluebersicht als Einstieg, ueber die Benutzer ihre zugewiesenen Demo-Faelle sehen und zur Bearbeitung auswaehlen
- ein gefuehrtes Chat-UI mit Fallbriefing, Artefakten und Aktionschips
- modernisierte, zweistufige UI mit Inbox-/Fallansicht und anschliessender Chatbearbeitung
- automatische Intent-Erkennung ueber
/api/conversation - strukturierte Requests ueber
/api/chat - folgende Aktionen im Anwendungscode:
- Chat / Fallanalyse
- Handover-Entwurf
- Similar Cases
- Evidence / Quellenansicht
- Triage mit moeglicher Workflow-Aktion
- interne Fallvermerke und eingehende externe Rueckmeldungen, die in den Retrieval-Kontext einfliessen
- sichtbare Warnungen, Sensitivitaetskennzeichnung pro Nachricht und optional einblendbare Meta-Informationen je Nachricht
- kurze, deterministische Fallbriefings zur besseren Exploration und stabileren Antworten
Wichtig: Die neuen Aktionschips im UI sind als plausible Arbeitsmodi gedacht. Sie ersetzen nicht die Anwendungslogik, sondern erleichtern die Exploration. Sicherheitskritische Entscheidungen bleiben weiterhin im deterministischen Backend.
./mvnw spring-boot:runoder mit echtem Key:
OPENAI_API_KEY=sk-... ./mvnw spring-boot:runDann im Browser: http://localhost:8080
Wichtiger Ist-Stand: Die App startet mit dem Default aus
application.yml, aber der aktuelle Code verdrahtet nur den echtenOpenAiChatService. Ohne gueltigenOPENAI_API_KEYschlagen LLM-gestuetzte Requests daher zur Laufzeit fehl bzw. liefern Fehlermeldungen zurueck.
- Repository in Codespaces oeffnen
- Warten bis der DevContainer gebaut ist
- Die Abhaengigkeiten werden beim Erstellen des Containers automatisch vorbereitet
- App direkt starten ueber eine der folgenden Varianten:
- Run and Debug -> Konfiguration
SecAssistApplicationstarten - oder Terminal / Run Task ->
SecAssist: spring-boot:runausfuehren
- Run and Debug -> Konfiguration
- Port 8080 wird automatisch weitergeleitet und als SecAssist geoeffnet
Hinweis: Fuer LLM-gestuetzte Requests wird weiterhin ein gueltiger OPENAI_API_KEY benoetigt.
Falls ein Codespace beim Container-Build mit einzelnen Dev-Container-Images scheitert,
verwendet das Repository nun stattdessen einen einfachen Dockerfile-basierten
Container auf Basis von maven:3.9.9-eclipse-temurin-21.
- Java 21
- Spring Boot 3.5.8
- Spring AI 1.1.0
- Maven (mit Wrapper)
- Statisches HTML/CSS/JS Frontend
- JUnit 5
| Rolle | Aktueller Zugriff |
|---|---|
contractor |
Nur freigegebene Fallsicht und Versand von Partner-Updates in den externen Rueckkanal |
employee |
Oeffentliche + interne Dokumente, Chat, Handover-Entwuerfe, Similar Cases |
security_analyst |
Voller Zugriff inkl. vertraulicher Inhalte und direkter Workflow-Aktionen |
Die Rolle wird im UI ausgewaehlt und mit jedem Request mitgeschickt. Es gibt bewusst keine echte Authentisierung.
- suspicious_supplier_invoice – Verdaechtige Rechnung von ACME Corp mit geaenderten Bankdaten und Compliance-Bezug
- strange_attachment – Unerwarteter
.iso-Anhang von bekanntem Kontakt - suspicious_vpn_reset – VPN-Passwort-Reset von unbekanntem Standort
- finance_phishing – Gezielte Phishing-Mail an die Finanzabteilung
Daneben existieren interne Vergleichsfaelle, die nur im Analysten-Kontext voll sichtbar sein sollen.
POST /api/conversation- nimmt nur
roleundmessage - erkennt Fall und Intent ueber
ConversationService
- nimmt nur
POST /api/chat- nimmt
role,caseId,message,action - erlaubt gezielte Tests von
chat,handover,similar_cases,evidence,workflow
- nimmt
GET /api/casesGET /api/rolesPOST /api/cases/{caseId}/notesPOST /api/cases/{caseId}/external-feedbackDELETE /api/notesGET /api/health
Die Anwendung enthaelt 5 absichtlich eingebaute Schwachstellen, die von den Teilnehmern im Code gefunden und gefixt werden sollen.
Im Handover-Modus verwendet der Retrieval-Policy-Filter fest kodierte Security-Team-Berechtigungen statt der Berechtigungen der aktuellen Rolle.
Ort: RetrievalService.retrieve()
Bei gezielten Similar-Cases-Anfragen erscheint fuer Nicht-Analysten ein plausibel wirkender Similarity-Hinweis aus dem eingeschraenkten Korpus, der weiterhin Anzahl, Themenbereich und Risikoprofil interner Vorfaelle leaket.
Ort: DemoCaseService.findSimilarCases() + ChatOrchestrator.handleSimilarCases() + ConversationService.processMessage()
Trusted und untrusted Quellen werden im Prompt in einen gemeinsamen Block gemischt, ohne klare Herkunftsmarkierung.
Ort: PromptBuilder.buildSystemPrompt() / appendConsolidatedGuidance()
Der evidenzbasierte Tool-Gate bewertet untrusted Lieferantenquellen, operative Kontextsignale und interne Fallnotizen zu grosszuegig. Dadurch kann ein employee im Lieferantenrechnungs-Case sicherheitsrelevante Aktionen ausloesen.
Ort: ToolPolicyService.evaluateAccess() / computeEvidenceScore() / effectiveThreshold() / sourceWeight()
Eingehende externe Rueckmeldungen aus einem freigegebenen Partner-/Reply-Kanal werden als interne, vertrauenswuerdige Chunks gespeichert und spaeter wie kuratierte Quellen behandelt.
Ort: RetrievalService.addExternalFeedback() / RetrievalService.addUserNote()
Bug 3 liefert der KI nicht sauber getrennte Quellen, Bug 4 erlaubt anschliessend die zu grosszuegige Ausfuehrung einer vorgeschlagenen Aktion. Zusammen kann ein employee einen Sicherheitsfall als False Positive herunterstufen.
Bug 5 schleust gefaelschte "interne" Partner-Rueckmeldungen ein, Bug 3 mischt sie in den generierten Kontext, Bug 4 erhoeht dadurch den Evidence-Score. Dadurch kann selbst ein spaeterer Fix an Bug 3 allein unzureichend sein.
Der zentrale Workshop-Case ist eine verdaechtige Lieferantenrechnung von ACME Corp. Im normalen Chat- und Workflow-Pfad werden Supplier-Informationen mit internen Richtlinien und frueheren Erkenntnissen kombiniert. Durch diese realistisch wirkende Trust-Vermischung und den zu grosszuegigen Evidence-Score kann ein employee den Fall als False Positive markieren – obwohl die zentrale Quelle untrusted ist und ein frueherer ACME-Incident im vertraulichen Postmortem dokumentiert ist.
Damit die Workshop-Cases reproduzierbarer bleiben, wird die strukturierte Triage in zwei Schritten verarbeitet:
- Das LLM erzeugt eine erste
TriageAssessment-Bewertung. - Dieselbe Bewertung wird noch einmal challengend geprueft.
Nur wenn beide Bewertungen dieselbe Aktion stuetzen, bleibt die empfohlene Aktion erhalten. Die endgueltige Tool-Freigabe liegt weiterhin ausschliesslich im deterministischen Anwendungscode (ToolPolicyService).
src/main/java/com/secassist/
├── config/ LlmConfig
├── model/ Role, DemoCase, DocumentChunk, ChatRequest/Response, NoteRequest, ToolActionResult
├── policy/ PolicyEngine
├── retrieval/ RetrievalService
├── llm/ LlmService, OpenAiChatService
├── tools/ ToolPolicyService, IncidentWorkflowService
├── service/ DemoCaseService, PromptBuilder, ChatOrchestrator, ConversationService
└── web/ ApiController
src/main/resources/
├── data/documents/ Markdown-Dokumente
├── data/chunks.json Vorbereitete Retrieval-Chunks
└── static/ HTML, CSS, JS
| Variable | Beschreibung | Aktueller Stand |
|---|---|---|
OPENAI_API_KEY |
Key fuer den echten OpenAI-Pfad | aktiv verwendet |
Aktueller Ist-Stand: Das Repository enthaelt derzeit keinen verdrahteten Mock-LLM-Pfad.
Die Anwendung ist deshalb fuer LLM-gestuetzte Requests momentan auf OPENAI_API_KEY
angewiesen. Die .env.example bildet diesen Ist-Stand bewusst direkt ab.
./mvnw test- Das Red Team versucht, die Schwachstellen auszunutzen (z. B. als
employeeeinen Fall falsch herunterzustufen) - Das Blue Team identifiziert die Bugs im Code und setzt Fixes um
- Die Schwachstellen sind mit
SCHWACHSTELLE [BUG_NAME]im Code kommentiert - Die Schwachstellen sind absichtlich eingebaut und kein Versehen