
Scannt Code-Diffs mit Kontext, um einen Auswirkungsgraphen zu erstellen, und nutzt LLMs, um Schwachstellen zu finden. Unterstützt Multi-Repo-Scans und CI-Gating mit SARIF-Ausgabe.
Diff-Security-Scanner übersehen die Auswirkungen von Änderungen – Zairo findet diese Auswirkungen und sucht nach Schwachstellen. Zairo scannt, was sich in Ihrem Code geändert hat, mit Kontext, erstellt einen Teilgraphen zum Ansehen und findet Schwachstellen mithilfe von LLMs Ihrer Wahl.

pipx install zairo
# Scannt alles, was Sie noch nicht committet haben
zairo .
# Scannt einen PR-/Branch-Diff
zairo . --base main --target HEAD
# Lässt den Build fehlschlagen, wenn etwas mit hoher Schwere auftaucht
zairo . --base main --target HEAD --fail-on high
Geben Sie ihm mehr als ein Repository, entweder als zusätzliche Argumente oder eines pro Zeile in einer --repos-file (oder beides, zu einer Liste zusammengeführt), und es wechselt von selbst in den Multi-Repo-Modus: Jedes Repository erhält seinen eigenen Bericht, plus eine kombinierte Zusammenfassung.
zairo backend frontend infra --base main --fail-on high -o zairo_multi_out
--base/--target (und jede andere Option) gelten auf dieselbe Weise für jedes Repository in der Liste, daher passt der Multi-Repo-Modus am besten, wenn alle gegen dasselbe diffen (z. B. das main aller). Repositories mit unterschiedlichen Konventionen benötigen separate Ausführungen.
Was gescannt werden soll
--base, -b (keine): Ref, von dem aus diffed wird, z. B. main oder HEAD~3. Wenn weggelassen, scannt zairo nicht committete Änderungen.--target, -t (keine): Ref, zu dem diffed wird. Benötigt --base; wenn weggelassen (mit gesetztem --base), diffed es gegen Ihren Arbeitsbaum.--depth, -d (1): Wie viele Hops von Aufrufern/Aufgerufenen in den Auswirkungsgraphen um jede Änderung herum gezogen werden sollen.--language, -l (auto): Erzwingt eine Sprache, anstatt Trailmark die automatische Erkennung zu überlassen.LLM-Scanning
--graph-only (aus): Überspringt den Schwachstellen-Scan und erstellt nur den Auswirkungsgraphen – keine Befunde, kein report.sarif.--model (gemini/gemini-2.5-pro): Beliebige LiteLLM-Modellzeichenkette.--concurrency, -c (5): Parallele LLM-Anfragen innerhalb des Scans eines Repository.--batch-size (1): Gruppiert diese Anzahl von Knoten in eine einzige LLM-Anfrage statt eines Aufrufs pro Knoten – weniger Anfragen (hilft bei Provider-Ratenlimits), auf Kosten einer gemeinsamen Fehlerisolierung: Eine schlechte/fehlerhafte Antwort lässt jeden Knoten in diesem Batch fehlschlagen, nicht nur einen. Das Caching bleibt in beiden Fällen pro Knoten.--max-tokens (4096): Ausgabebudget pro Anfrage. Reasoning-Modelle verbrauchen dies auch für internes Denken, erhöhen Sie es also, wenn Sie leere Antworten sehen.--cache / --no-cache (Cache an): Überspringt das erneute Scannen von Code, der seit dem letzten Lauf unverändert ist (zwischengespeichert nach Inhalts-Hash in <output>/.llm_cache.json).--tokens (aus): Gibt aus, wie viele Tokens der Scan tatsächlich verbraucht hat (Cache-Treffer zählen nicht, da sie keinen Aufruf ausgelöst haben).Ausgabe & Gating
--output, -o (zairo_out): Wohin die Berichte gehen. Multi-Repo-Modus: Jedes Repository erhält sein eigenes <output>/<repo-slug>/, plus ein kombiniertes rollup.* hier ebenfalls.--fail-on (keine): Beendet mit Nicht-Null-Exitcode, wenn ein Befund auf oder über dieser Schwere auftaucht (low/medium/high/critical). Fehler, wenn mit --graph-only kombiniert (nichts, worauf gegated werden könnte). Multi-Repo-Modus: Wird über alle Repositories kombiniert geprüft. Siehe CI / PR-Gating.--verbose, -v (aus): Gibt Schritt für Schritt aus, was passiert (Git-Befehle, Worktree-Einrichtung, Scan-Fortschritt pro Knoten).--debug, -vv (aus): Alles, was --verbose ausgibt, plus den exakten Prompt, der an das LLM gesendet wird, und dessen rohe Antwort für jeden Knoten – geschrieben in <output>/debug.log (pro Repository im Multi-Repo-Modus), da es zu viel ist, um es auf der Konsole auszugeben.Nur Multi-Repo-Modus
--repos-file (keine): Ein Repository-Pfad pro Zeile (#-Kommentare erlaubt), zusammengeführt mit allen direkt angegebenen Repositories.--repo-concurrency (1): Wie viele Repositories gleichzeitig gescannt werden sollen. Die Gesamtzahl der laufenden LLM-Anfragen kann --concurrency × --repo-concurrency erreichen, achten Sie also auf die Ratenlimits Ihres Providers. Über 1 hinaus gibt der Fortschritt bei Abschluss eine Zusammenfassungszeile pro Repository aus, statt Live-Schritt-für-Schritt-Details.--continue-on-error / --stop-on-error (fortsetzen): Scannt den Rest der Liste weiter oder stoppt, wenn ein Repository fehlschlägt. In beiden Fällen lässt ein fehlgeschlagenes Repository den Gesamt-Exitcode fehlschlagen.Führen Sie jederzeit zairo --help aus, um dieselbe Liste von der CLI zu erhalten.
report.json (immer): Der rohe Auswirkungsgraph (Knoten, Kanten und alle angehängten Befunde) als Daten.report.html (immer): Ein eigenständiger, interaktiver Abhängigkeitsgraph-Viewer (Cytoscape.js). Klicken Sie auf einen Knoten, um dessen Befunde zu sehen.report.sarif (außer wenn --graph-only verwendet wird): Befunde in SARIF 2.1.0, für GitHub-Code-Scanning oder jeden anderen SARIF-Konsumenten. Wird immer geschrieben, auch bei einem sauberen Scan (ein leeres, aber gültiges Log), damit eine Scanning-Oberfläche zuvor gemeldete Warnungen als behoben markieren kann. Befunde werden nach CWE in Regeln gruppiert, wenn das Modell eine getaggt hat, sodass wiederkehrende Probleme derselben Art in einer Regel zusammengefasst werden, statt einer neuen pro Formulierungsvariante.Der Multi-Repo-Modus erzeugt dieselben drei Dateien pro Repository, plus rollup.json / rollup.html / rollup.sarif: Status- und Schweregrad-Zählungen pro Repository, eine Dashboard-Tabelle mit Links zu den Berichten jedes Repository und alle SARIF-Ergebnisse jedes Repository, zusammengeführt in ein Multi-Run-Log.
Eine Funktion/Klasse/ein Modul, das vollständig entfernt wurde (nicht nur bearbeitet), erscheint weiterhin in report.html mit dem Status deleted: ein gestrichelter, ausgeblendeter Knoten, der markiert, wo es früher war. Trailmarks Graph kann dies nicht von selbst darstellen (er spiegelt nur den Baum wider, wie er jetzt ist), daher erkennt zairo Löschungen separat: Es parst auch die geänderten Dateien, wie sie bei --base existierten (oder HEAD, wenn --base nicht angegeben wurde) und diffed die beiden Symbolmengen. Eine gelöschte Funktion wird niemals an den LLM-Scanner gesendet (es gibt keinen lebenden Code mehr zu scannen), daher trägt sie nur ihren Namen, ihre Art und ihren früheren Speicherort, niemals Befunde.
--fail-on <low|medium|high|critical> beendet mit Nicht-Null-Exitcode, wenn ein Befund auf oder über dieser Schwere gefunden wird (über alle Repositories kombiniert im Multi-Repo-Modus), sodass ein CI-Schritt einen Merge darauf blockieren kann. Ein paar Dinge, die wissenswert sind:
--graph-only kombiniert wird (es gäbe nichts, worauf gegated werden könnte).zairo . --base "$BASE_REF" --target HEAD --fail-on high -o zairo_out
Siehe examples/github-actions/zairo-pr-scan.yml
für einen vollständigen PR-Scan-Workflow: Er führt zairo auf dem PR-Diff aus, lädt report.sarif in das Code-Scanning von GitHub hoch und lässt den Job fehlschlagen, wenn das Gate fehlschlägt.