Wie die Detection Pipeline aufgebaut ist, welche Regeln greifen und warum Entropy-Detection den Unterschied macht
Serienosecrets
Teil 2 von 2
Unter der Haube
Im ersten Teil ging es darum, was nosecrets ist, warum es existiert und wie man es einrichtet. Dieser Artikel geht tiefer: Wie funktioniert die Detection Pipeline? Welche Regeln greifen und warum? Und was hat es mit der Entropy-Detection auf sich?
Architektur: Fünf spezialisierte Crates
nosecrets ist als Rust Workspace mit fünf Crates aufgebaut. Jeder Crate hat eine klare Verantwortung:
nosecrets-core ist das Herzstück. Die Detection Pipeline verarbeitet jede Datei in mehreren Stufen:
- Pfad-Filter — passt die Datei zu einem Ignore-Pattern?
- Keyword-Prefilter — Aho-Corasick sucht nach Schlüsselwörtern in einem Durchlauf
- Regex-Matching — nur Regeln, deren Keywords gefunden wurden, werden angewendet
- Struktur-Validierung — Charset, Länge, Prefix-Constraints prüfen
- Allowlist-Check — Pattern- und Value-Allowlists auf Config- und Regel-Ebene
- Inline-Comments —
@nosecrets-ignoreoder@nsiim Code - Fingerprint-Check — Content-Hash in
.nosecretsignore - Entropy-Detection — Shannon-Entropie für unbekannte Tokens
Der Aho-Corasick-Prefilter ist entscheidend für die Performance. Statt jede Regex gegen jede Zeile zu testen, prüft er in einem einzigen Durchlauf, welche Keywords überhaupt vorkommen. Nur die zugehörigen Regeln werden dann mit der teuren Regex ausgewertet.
Was erkannt wird
nosecrets hat über 60 Regeln in sieben Kategorien, alle als TOML spezifiziert und zur Build-Zeit in das Binary kompiliert:
Cloud Provider — AWS Access Keys (AKIA/ABIA/ACCA/ASIA Prefix mit exakt 20 Zeichen), GCP API Keys (AIza-Prefix), Azure Storage Keys, Cloudflare API Tokens, DigitalOcean Tokens.
Code-Plattformen — GitHub PATs (ghp_), Fine-Grained PATs (github_pat_), GitLab PATs (glpat-), npm Tokens, PyPI Tokens, Slack Tokens (xoxp/xoxb/xoxo/xoxa/xoxr/xoxs), Discord Tokens.
Deployment — Netlify, Fly.io (fo1_, fm1_, fm2_), Heroku, Vercel, Railway, Render, Supabase.
Payment — Stripe Secret Keys (sk_live_), Restricted Keys (rk_live_), Webhook Secrets (whsec_), PayPal, Square.
Datenbanken — PostgreSQL, MySQL, MongoDB, Redis und SQL Server Connection URIs mit Passwort-Extraktion. JDBC Connection Strings.
Kommunikation — SendGrid (SG.-Prefix), Twilio, Mailchimp, Mailgun.
Generisch — Private Keys (PEM: RSA, EC, DSA, OpenSSH, PGP), generische API-Key und Secret-Patterns, Password Assignments, Basic Auth Header.
Entropy-Detection: Das Unbekannte finden
Regelbasierte Erkennung hat eine Grenze: Sie findet nur, was sie kennt. Ein API-Key eines obskuren SaaS-Dienstes, der kein bekanntes Prefix hat, rutscht durch.
Dafür gibt es die Entropy-Detection. Sie berechnet die Shannon-Entropie eines Tokens — ein Maß dafür, wie zufällig ein String ist. Ein echtes Secret hat typischerweise hohe Entropie (viele verschiedene Zeichen, kein erkennbares Muster). Ein normaler Variablenname oder ein Platzhalter hat niedrige Entropie.
[entropy]
enabled = true
min_length = 20
threshold = 4.2
require_context = true
require_context ist der wichtigste Parameter. Wenn aktiviert, werden High-Entropy-Strings nur gemeldet, wenn sie in der Nähe von secret-relevanten Variablennamen stehen: secret, token, key, auth, password, credential, bearer, api_key, private, access_token, refresh_token.
Das reduziert False Positives drastisch. Ohne Context-Requirement würde jeder Base64-String, jeder lange Hash und jede UUID gemeldet. Mit Context werden nur Strings geflaggt, die wie Secrets zugewiesen werden.
Zusätzlich filtert die Entropy-Detection bekannte Platzhalter (example, changeme, your_token, todo, fixme, dummy, sample, mock), reine Hex-Strings, UUIDs und bekannte Formate automatisch aus.
Konfiguration für Fortgeschrittene
Installation und Grundkonfiguration stehen im ersten Teil. Hier die erweiterten Möglichkeiten:
Entropy-Konfiguration in .nosecrets.toml
[entropy]
enabled = true
min_length = 20
threshold = 4.2
require_context = true
[entropy.allow]
patterns = ["^[a-f0-9]{32,}$"]
Allowlists auf Regel-Ebene
Neben der globalen Allowlist in .nosecrets.toml können einzelne Regeln eigene Allowlists haben — definiert direkt in der TOML-Regel. Das ist nützlich für Provider-spezifische Testkeys, die ein bekanntes Suffix haben.
Performance
Die Performance kommt aus der Kombination von drei Optimierungen:
Aho-Corasick Prefilter — alle Keywords aller Regeln werden in einem einzigen Automaten zusammengefasst. Ein Durchlauf durch den Text reicht, um zu wissen, welche Regeln überhaupt relevant sind.
Parallele Verarbeitung — rayon verteilt die Dateiverarbeitung auf alle verfügbaren CPU-Kerne. Bei einem Scan von 100 Dateien arbeiten alle Kerne gleichzeitig.
Lazy Regex Compilation — Regexes werden nur einmal kompiliert und wiederverwendet. once_cell sorgt dafür, dass die Initialisierung thread-safe und ohne Lock-Contention passiert.
Das Ergebnis: Startup unter 20ms, Durchsatz über 200 MB/s, Speicherverbrauch unter 50 MB. In der Praxis bedeutet das: Der Pre-Commit-Hook ist schneller fertig, als die Git-UI den Status aktualisiert.
Regelformat
Eigene Regeln können als TOML definiert werden:
[[rule]]
id = "my-internal-token"
name = "Internal API Token"
severity = "high"
pattern = '''\b(itk_[a-zA-Z0-9]{32})\b'''
keywords = ["itk_"]
capture = 1
[rule.validate]
prefix = ["itk_"]
charset = "a-zA-Z0-9"
length = 36
[rule.allow]
patterns = ["EXAMPLE$", "TEST$"]
Das Format ist bewusst einfach gehalten. keywords sind die Aho-Corasick-Hints — wenn keines der Keywords in der Datei vorkommt, wird die Regex gar nicht erst ausgewertet. capture gibt an, welche Capture Group das eigentliche Secret enthält. validate prüft strukturelle Constraints nach dem Regex-Match.
Warum Rust
Drei Gründe:
Performance ohne Kompromisse. Ein Pre-Commit-Hook muss schnell sein. Python-basierte Scanner haben spürbare Startzeiten. Rust hat keine Runtime, kein GC, keine Interpreter-Overhead.
Plattformübergreifende Binaries. Ein einziges Build erzeugt native Binaries für macOS (Intel + ARM), Linux und Windows. Das npm-Paket liefert das passende Binary automatisch aus.
Korrektheit. Regex-Handling, Unicode, Parallelität — Rust’s Type-System und Ownership-Modell verhindern ganze Fehlerklassen, die in anderen Sprachen manuell abgesichert werden müssen.
Einordnung
nosecrets ist kein Ersatz für CI-basierte Security-Scans, SAST-Tools oder manuelle Code-Reviews. Es ist die erste Verteidigungslinie: ein schneller, offline-fähiger Check, der die offensichtlichsten Fehler abfängt, bevor sie das Repository erreichen.
Der Fokus auf Pre-Commit statt History-Scanning ist eine bewusste Entscheidung. Wenn ein Secret im Commit verhindert wird, muss man die History nicht bereinigen. Prävention statt Forensik.
Das Tool ist Open Source, die Regeln sind erweiterbar, und Contributions — besonders neue Erkennungsregeln — sind willkommen: github.com/casoon/nosecrets