SAST und CodeQL mit KI: Einsatz und Grenzen
Statische Codeanalyse findet Schwachstellen, bevor der Code läuft. In der Praxis bremst sie meist nicht die Erkennung aus, sondern die Menge der Meldungen. Sprachmodelle (LLMs) setzen genau dort an: bei Spezifikationen, Triage und Korrekturvorschlägen. Dieser Artikel zeigt, wie SAST und CodeQL arbeiten, was die Kombination mit KI belegbar verbessert und wo Lizenz, Fehlalarme und Modellrisiken Grenzen setzen.
Was SAST prüft und was CodeQL anders macht
SAST (Static Application Security Testing) analysiert Quellcode oder Zwischenformen, ohne das Programm auszuführen. Einfache Werkzeuge suchen Muster, etwa den Aufruf einer unsicheren Funktion. Sie erkennen nicht, ob nicht vertrauenswürdige Eingaben diese Stelle überhaupt erreichen.
Taint-Tracking, eine Form der Datenflussanalyse, schließt diese Lücke. Sie verfolgt Werte von Quellen (Eingaben von außen) zu Senken (sicherheitsrelevante Operationen wie eine SQL-Ausführung). Eine Barriere oder ein Sanitizer auf dem Weg unterbricht den Fluss.
CodeQL geht beim Aufbau anders vor als ein Mustersuchwerkzeug. Beim Erzeugen der Datenbank extrahiert es Syntaxbaum, Kontrollfluss und Typinformationen in eine relationale Datenbank je Sprache. Abfragen schreiben Sie in QL, einer deklarativen, objektorientierten Logiksprache (Avgustinov et al., ECOOP 2016). Dieselbe Datenbank beantwortet beliebig viele Abfragen.
Laut CodeQL-Dokumentation deckt CodeQL C/C++, C#, Go, Java, Kotlin, JavaScript, TypeScript, Python, Ruby, Rust, Swift und GitHub Actions ab. Bei kompilierten Sprachen braucht die Extraktion Zugriff auf den Build. Welche Sprachen ohne Build auskommen, steht in der aktuellen CodeQL-Dokumentation.
Taint-Analyse am Beispiel
Das folgende Beispiel ist generisch und stammt aus keinem Kundenprojekt. Die erste Variante baut die SQL-Abfrage per String zusammen. Die zweite übergibt den Wert als Parameter.
# anfällig: Eingabe landet im SQL-Stringdef get_order(request, cursor): order_id = request.args["id"] # Quelle sql = f"SELECT * FROM orders WHERE id = {order_id}" # Zusammenbau cursor.execute(sql) # Senke # behoben: Wert wird gebunden, nicht eingefügtdef get_order(request, cursor): order_id = request.args["id"] cursor.execute("SELECT * FROM orders WHERE id = %s", (order_id,))Der Platzhalter %s hängt vom Datenbanktreiber ab. Andere Treiber nutzen ? oder benannte Parameter.
In QL beschreibt eine Abfrage Quellen und Senken und lässt die Bibliothek den Fluss berechnen. Die folgende Abfrage ist verkürzt und dient der Illustration. Die Standard-Suiten enthalten die Abfrage bereits. Eigene Abfragen kommen für interne Frameworks in Frage, deren Quellen und Senken die Standardmodelle nicht kennen.
/** * @name SQL-Abfrage aus Benutzereingabe (Beispiel) * @kind path-problem * @id example/sql-injection */import pythonimport semmle.python.Conceptsimport semmle.python.dataflow.new.DataFlowimport semmle.python.dataflow.new.TaintTrackingimport semmle.python.dataflow.new.RemoteFlowSources module SqlConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } predicate isSink(DataFlow::Node sink) { sink = any(SqlExecution e).getSql() }} module SqlFlow = TaintTracking::Global<SqlConfig>;import SqlFlow::PathGraph from SqlFlow::PathNode source, SqlFlow::PathNode sinkwhere SqlFlow::flowPath(source, sink)select sink.getNode(), source, sink, "SQL-Abfrage aus $@.", source.getNode(), "Benutzereingabe"Warum klassisches SAST ausbremst
Die IRIS-Studie (ICLR 2025) benennt zwei Ursachen, die auch CodeQL treffen. Beide lassen sich an konkreten Mechanismen festmachen.
Fehlende Spezifikationen für Bibliotheken
Taint-Analyse braucht Modelle: Welche Methode liefert Eingaben, welche ist eine Senke, welche reinigt Werte? Für Drittbibliotheken fehlen diese Angaben oft. Das Ergebnis sind False Negatives, also Schwachstellen ohne Alert.
Fehlender Kontext
Auch bei vollständigen Spezifikationen fehlt der Analyse das Verständnis für Bedingungen, Validierung und Absicht. Das erzeugt Fehlalarme. Entwickler müssen viele potenziell falsche Meldungen durchsehen und verlieren dabei Zeit.
Grenzen der Methode
Statische Analyse nähert Programmverhalten an. Exakt ist das im Allgemeinen nicht berechenbar (Satz von Rice). Reflection, dynamische Auflösung und Konfiguration zur Laufzeit machen Flüsse schwer verfolgbar. Auch Fehler in der Geschäftslogik, etwa fehlende Autorisierungsprüfungen, lassen sich kaum als Quelle-Senke-Muster ausdrücken.
Was LLMs verändern
LLMs ersetzen die Analyse nicht. Sie ergänzen sie an den Stellen, an denen Regeln fehlen oder Kontext nötig ist. Vier Einsatzstellen sind dokumentiert.
Spezifikationen ableiten
IRIS lässt ein Modell Quellen und Senken aus Bibliotheks-APIs ableiten und gibt sie an CodeQL weiter. Auf dem Benchmark CWE-Bench-Java fand IRIS mit GPT-4 55 Schwachstellen, CodeQL allein 27.
Alerts bewerten
Das Modell erhält den Codepfad samt Umgebung und urteilt, ob der Alert echt ist.
Korrekturen vorschlagen
Copilot Autofix erzeugt Korrekturen zu CodeQL-Alerts. GitHub nennt für die Beta-Phase mehr als 90 % abgedeckte Alert-Typen in JavaScript, TypeScript, Java und Python. Mehr als zwei Drittel der Funde ließen sich mit wenig oder keiner Nacharbeit beheben. Das ist eine Herstellerangabe.
Agentisch arbeiten
Seit Juli 2026 gibt es Agentic Autofix als Public Preview. Es untersucht die Codebasis und prüft den Fix durch einen erneuten CodeQL-Lauf. Es verbraucht AI Credits und Actions-Minuten. Ob zusätzlich Tests laufen, nennt die Ankündigung nicht.
Wie belastbar sind die Zahlen?
| Aussage | Quelle | Einstufung |
|---|---|---|
| 55 statt 27 gefundene Schwachstellen auf CWE-Bench-Java | IRIS, ICLR 2025 | begutachtet |
| False Discovery Rate 84,82 %, 5,21 Prozentpunkte unter CodeQL | IRIS, ICLR 2025 | begutachtet |
| Mehr als 90 % der Alert-Typen, rund zwei Drittel ohne oder mit wenig Nacharbeit | GitHub Blog | Herstellerangabe |
| Verbesserte Fehlalarmerkennung mit Gedächtnis aus früheren Alerts (Memoir) | arXiv-Preprint | Preprint |
| 91 % weniger Fehlalarme (225 auf 20) gegenüber Semgrep allein (SAST-Genius) | arXiv-Preprint | Preprint |
Die IRIS-Ergebnisse stammen aus einem Java-Benchmark mit bekannten Schwachstellen. Sie sagen nichts über beliebige Unternehmensanwendungen aus. Die Preprints sind nicht unabhängig geprüft.
Einsatz in der Pipeline
CodeQL läuft typischerweise in der CI und meldet Ergebnisse im SARIF-Format als Code-Scanning-Alerts. Bei Pull Requests erscheinen die Funde direkt am Diff. Das folgende Workflow-Beispiel ist generisch.
name: codeqlon: pull_request: push: branches: [main] schedule: - cron: "17 3 * * 1" # wöchentlicher Volllauf jobs: analyze: runs-on: ubuntu-latest permissions: contents: read security-events: write strategy: matrix: language: [python, javascript-typescript] steps: - uses: actions/checkout@v7 - uses: github/codeql-action/init@v4 with: languages: ${{ matrix.language }} queries: security-extended - uses: github/codeql-action/analyze@v4 with: category: "/language:${{ matrix.language }}"Drei Stellschrauben bestimmen das Ergebnis. Die Query-Suite legt fest, wie breit gesucht wird: Standard, security-extended oder security-and-quality. Die Kategorie je Sprache hält Ergebnisse getrennt. Der Trigger entscheidet, ob Funde vor dem Merge oder erst danach auffallen.
Wo KI in der Pipeline sitzt
Zwei Architekturen sind denkbar. Die folgende Gegenüberstellung ist ein Architekturbeispiel, keine Messung.
| Merkmal | Herstellerfunktion (Autofix) | Eigene Triage-Stufe über SARIF |
|---|---|---|
| Aufbau | In GitHub integriert, Auslösung am Alert | Separater Job liest SARIF, bewertet, schreibt Kommentar oder Label |
| Modellwahl | Vom Anbieter vorgegeben | Frei, auch selbst betriebenes Modell möglich |
| Codeabfluss | Code geht an den Dienst des Anbieters | Hängt vom gewählten Modell und Betrieb ab |
| Wartung | Beim Anbieter | Prompts, Schwellen und Auswertung liegen im eigenen Betrieb |
| Kosten | Lizenz, bei Agentic Autofix zusätzlich AI Credits und Actions-Minuten | Modellbetrieb und Pipeline-Laufzeit |
Grenzen
Lizenz
Die CodeQL-Bedingungen von GitHub erlauben die Analyse von Open-Source-Codebasen unter einer OSI-genehmigten Lizenz. Liegt ein solcher Code auf GitHub.com, ist auch die Datenbankerzeugung in CI und CD erlaubt. Für andere Codebasen, etwa private Repositories, gelten diese Rechte nicht. Dort greift eine kostenpflichtige Lizenz für GitHub Code Security oder GitHub Advanced Security.
Erkennungsgrenzen
| Ursache | Wirkung | Hilft ein LLM? |
|---|---|---|
| Fehlende Modelle für Bibliotheken | False Negatives | Teilweise, durch abgeleitete Quellen und Senken (IRIS) |
| Fehlender Kontext im Datenfluss | Fehlalarme | Teilweise, durch Triage mit Umgebungscode |
| Fehlende Autorisierung, Logikfehler | Kaum als Quelle-Senke-Muster fassbar | Nicht belegt |
| Dynamisches Verhalten zur Laufzeit | Flüsse nicht vollständig verfolgbar | Nicht belegt |
Fehlalarme bleiben
Selbst im besten Ergebnis der IRIS-Studie liegt die False Discovery Rate bei 84,82 %. Die Mehrzahl der gemeldeten Funde war also weiterhin falsch. Der Gewinn liegt im Abstand zu CodeQL allein, nicht in einem fehlalarmfreien Ergebnis.
Risiken beim Einsatz von LLMs
- Nichtdeterminismus: Dieselbe Eingabe kann zu unterschiedlichen Urteilen führen. Triage-Ergebnisse sind deshalb nur eingeschränkt reproduzierbar.
- Manipulation über Code: Kommentare und Strings im analysierten Code gelangen in den Prompt. Ein Modell kann dadurch beeinflusst werden.
- Codeabfluss: Bei Cloud-Modellen verlässt Code die eigene Umgebung. Die Vertragslage und die Datenschutzfragen klärt Ihre Datenschutz- und Rechtsberatung.
- Fehlerhafte Fixes: Ein verschwundener Alert beweist nicht, dass das Verhalten erhalten blieb. Dafür braucht es Tests und Review.
- Kostenmodell: Agentische Läufe verbrauchen Credits und Pipeline-Minuten. Die Kosten wachsen mit der Zahl der zugewiesenen Alerts.
Betrieb
Der Datenbankaufbau und die Laufzeit wachsen mit der Codebasis. Kompilierte Sprachen brauchen je nach Sprache und Build-Modus einen funktionierenden Build in der CI. Alerts brauchen einen Prozess: wer bewertet sie, wer schließt sie mit welcher Begründung, und wie lange darf ein Fund offen bleiben.
Einordnung
SAST bleibt eine Methode mit klaren Grenzen. LLMs verschieben diese Grenzen an zwei Stellen: bei fehlenden Spezifikationen und bei der Triage. Die Zahlen stammen überwiegend aus Benchmarks und von Herstellern. Wie gut die Kombination in einer bestimmten Codebasis arbeitet, zeigt erst ein Lauf auf diesem Code.
Quellen
- GitHub Blog: Found means fixed: Introducing code scanning autofix, powered by GitHub Copilot and CodeQL (öffnet in neuem Tab)
- GitHub Changelog: Agentic autofix for code scanning alerts in public preview (öffnet in neuem Tab), Juli 2026
- Microsoft DevOps Blog: Copilot Autofix for GitHub Advanced Security for Azure DevOps (öffnet in neuem Tab), 11. Juni 2026
- CodeQL-Dokumentation: Supported languages and frameworks (öffnet in neuem Tab)
- GitHub: GitHub CodeQL Terms and Conditions (öffnet in neuem Tab)
- Li et al.: IRIS: LLM-Assisted Static Analysis for Detecting Security Vulnerabilities (öffnet in neuem Tab), ICLR 2025
- arXiv: Memoir: Learning, Verifying, and Evolving False-Positive Memories for Static Application Security Testing Tools (öffnet in neuem Tab) (Preprint)
- arXiv: LLM-Driven SAST-Genius: A Hybrid Static Analysis Framework for Comprehensive and Actionable Security (öffnet in neuem Tab) (Preprint)
- Avgustinov, de Moor, Jones, Schäfer: QL: Object-oriented Queries on Relational Data (öffnet in neuem Tab). ECOOP 2016, Schloss Dagstuhl.
- Rice, H. G.: Classes of Recursively Enumerable Sets and Their Decision Problems (öffnet in neuem Tab). Transactions of the American Mathematical Society, 1953.
Sicherheitsprüfung bei Seovantis
Sicherheitsprüfungen führt Seovantis durch, wenn sie in der technischen Leistungsbeschreibung vereinbart sind. Wie die Prüfung vor der Übergabe abläuft, steht auf der Seite Arbeitsweise.
Ein ähnliches Vorhaben?
Schildern Sie kurz Ihre Ausgangslage. Ich melde mich innerhalb eines Werktags.