Dokumentation
Signatur-Feeds
Ein Signatur-Update ist die gefährlichste Routineoperation, die ein Scanner ausführt. Es kann in einer Minute tausend gesunde Dateien bei hundert Kunden in Quarantäne verschieben. Alles hier existiert, um genau das zu verhindern.
Generationen statt Updates
Ein Regelsatz ist kein Strom von Änderungen, sondern eine Generation: ein unveränderliches,
signiertes Verzeichnis. Vendor-Generations-IDs lauten exakt YYYYMMDDTHHMMSSZ-NNNN, zum Beispiel
20260903T120000Z-0001. Lokale Overlays verwenden local-<64 hex characters>.
<gen>/
├── manifest.json
├── manifest.sig
├── yara/ *.yar, rules.yarc, rules.yarc.meta
├── hashes/ *.hsb + *.hsb.meta.json
├── allow/ *.sha256
└── clam/ *.ndb, *.hdb, *.fp, *.sfp, *.crtdb
manifest.json ist kanonisches JSON und enthält gen, created_at, expires_at,
Engine-Anforderungen (yara_version_min, clamav_min), die Dateiliste, Zählwerte und eine
key_id. Jede Datei trägt einen SHA-256-Digest, eine Größe und die vollständige Provenienz:
Quell-URI, SPDX-Lizenz, Autor, Upstream-Commit und die Angabe, ob sie verändert wurde.
manifest.sig ist eine kanonische JSON-Sidecar-Datei mit einer Ed25519-Signatur; die Key-ID
besteht aus den ersten acht Bytes des SHA-256 des öffentlichen Schlüssels.
Die Schema-Grenzen sind hart: höchstens 4096 Manifest-Dateien, höchstens zehn Millionen je Zählwert, ein Ablauf höchstens zehn Jahre nach der Erstellung und ein bis 4096 eindeutige Generationen in einem Index.
Download und Verifikation
Der Client verlangt HTTPS, die übliche Zertifikatsprüfung und dieselbe Origin für Basis-URL, Weiterleitungen und Artefakte. Voreinstellungen: 30 s HTTP-Timeout, 16 MiB je Antwort, 64 MiB je Datei, 512 MiB je Generation und 4096 Dateien.
Die Reihenfolge ist entscheidend: Der Client prüft den Manifest-Digest aus dem signierten Index, bevor er die Manifest-Signatur prüft, dann jede Datei nach Größe und Digest, und verifiziert anschließend die gesamte Generation erneut aus dem temporären Verzeichnis, bevor er sie atomar ins Staging veröffentlicht.
Ein normaler Abruf akzeptiert nur eine Generation, die strikt neuer als die aktive Vendor-Basis ist. Ältere Generationen sind ausschließlich über einen ausdrücklich angeforderten Rollback erreichbar — der selbst vollständig verifiziert wird und nicht abgelaufen sein darf.
Widerruf
Das signierte Array revoked eines Index wird in eine Tombstone-Datei im Append-only-Verfahren
übernommen, bevor irgendeine neue Generation ausgewählt wird. Einträge werden nie entfernt,
auch dann nicht, wenn ein späterer Index sie nicht mehr aufführt. Eine aktive oder gespeicherte
widerrufene Generation wird sofort deaktiviert, und der Manager lädt anschließend die neueste
nicht widerrufene, vollständig verifizierte Generation. Gibt es keinen sicheren Ersatz, bleibt
der Zustand sichtbar fehlerhaft, statt stillschweigend einen widerrufenen Feed nachzuladen. Ein
Rollback auf eine per Denylist gesperrte Generation ist dauerhaft blockiert.
Das Korpus-Gate
Keine Generation wird ohne bestandenes Gate aktiviert:
- Es müssen sowohl ein Known-good-Korpus als auch ein Known-bad-Korpus vorhanden sein und jeweils mindestens eine sichere, reguläre Datei enthalten. Symlinks, Spezialdateien, unsichere Eigentümer oder Rechte und unvollständige Scan-Ergebnisse werden zurückgewiesen.
- Der Compiler muss fehlerfrei zurückkehren, und bei Vendor-Generationen müssen die Generation des Regelsatzes, die Regelanzahl und die Hash-Anzahl exakt mit dem Manifest übereinstimmen.
- Ein Lizenzverstoß führt immer zu einer harten Zurückweisung. Ein einfacher Compiler ohne Lizenzbewusstsein wird nicht akzeptiert, auch wenn er Erfolg meldet.
- Engine-Anforderungen werden gegen die Versionen durchgesetzt, die das Worker-Protokoll tatsächlich meldet. Fehlende, fehlerhafte, überlange oder mit einem Pre-Release-Suffix versehene Versionen werden fail-closed zurückgewiesen, ebenso eine Version unterhalb dessen, was das Manifest verlangt.
- Jeder
malicious-Treffer im Good-Korpus ist ein hartes Scheitern des Gates. Die Erkennungsrate am Bad-Korpus wird als Metrik erfasst; unterhalb von 90 % erzeugt sie eine Warnung und keine automatische Zurückweisung, denn eine niedrige Rate ist ein Qualitätsproblem und ein Fehlalarm ist ein Ausfall.
Aktivierung
Aktivierung und Rollback sind root-exklusiv. Signatur, Kanonizität des Manifests und jeder Datei-Digest werden unmittelbar vor der Umschaltung erneut verifiziert — auch nach dem Verschieben aus dem Staging, denn ein langer Gate-Durchlauf ist ein langes Zeitfenster.
Die Generation wird in das Feed-Wurzelverzeichnis verschoben, ohne etwas zu überschreiben, und
der Symlink current wird über einen temporären Symlink und rename atomar getauscht. Erst
danach lädt der Worker neu, verwirft der Cache die vorherige Generation, und die Audit- und
Store-Einträge werden geschrieben. Fehler lösen eine Best-Effort-Kompensation aus, die den
vorherigen Symlink, den Worker-Zustand und die Clam-Dateien wiederherstellt. Wo eine
Kompensation keinen konsistenten Zustand herstellen kann, wird der tatsächlich geladene Zustand
so gemeldet, wie er ist, mitsamt dem Fehler, statt fälschlich eine Zurückweisung zu behaupten.
Die Aufbewahrung schützt immer current, ausdrücklich bewahrte Generationen und jede
Vendor-Basis, auf die sich ein lokales Overlay bezieht; darüber hinaus überleben die neuesten
keep_generations (Voreinstellung 3).
Der Circuit Breaker
Ein mandantenübergreifender Circuit Breaker vergleicht die letzte Stunde mit dem 24-Stunden-Mittel. Standardmäßig verlangt er mindestens 50 Quarantänen und mehr als das Zehnfache des Mittels und zusätzlich mindestens drei verschiedene Konten sowie mindestens 20 % aller aktiven Konten. Beide Konto-Schwellen sind konfigurierbar.
Der Zweck dieser beiden zusätzlichen Bedingungen ist unmissverständlich: Ein einzelnes Konto kann niemals einen serverweiten Rollback auslösen. Ein Kunde, der hundert infizierte Dateien hochlädt, ist ein Kundenproblem und kein Regelproblem.
Heuristische, fehlende oder widersprüchliche Signale lösen nie einen Rollback aus. Nach einem erfolgreichen Rollback werden Alarm- und Audit-Hooks bei Bedarf wiederholt — ohne einen zweiten Rollback.
Lizenzen und Provenienz
Der Build lässt nur DRL-1.1, BSD-3-Clause, Apache-2.0 und MIT zu (dazu GPL-2.0-only für
ClamAV-Datenbanken). Zurückgewiesene Dateien und Regeln erscheinen deterministisch auf stderr;
eine fehlende Provenienz führt nie zu einem stillen Überspringen.
Für jede Regel, die in einem Laufzeitsignal erscheinen kann, müssen die Metadaten license,
author und eines von reference, ref oder source vorhanden sein und exakt mit der
Provenienz-CSV übereinstimmen. Eine CSV-Zeile allein genügt nicht. Abweichende oder fehlende
Attribution wird fail-closed verworfen.
Wo eine Upstream-Lizenz verlangt, dass Autor, Regel-URI und Lizenzhinweis bis in die Erkennungsberichte erhalten bleiben, geschieht das auch: Die Attribution wandert in die Panel-Anzeige und in die Benachrichtigungs-E-Mail.
Die Entscheidungen zu den Quellen, klar benannt:
| Quelle | Entscheidung |
|---|---|
ClamAV daily, main, bytecode | wird je Server von freshclam bezogen, nicht mitgeliefert |
| Aggregierte YARA-Pakete Dritter | nie als Ganzes übernommen; ausschließlich einzelne geprüfte Regeln mit zulässiger Lizenz und vollständiger Provenienz |
| Regelsätze unter einer Attributionslizenz | mitgeliefert, mit Attribution bis in Oberfläche und E-Mail |
| Quellen mit unklaren Bedingungen zur kommerziellen Weiterverbreitung | bis zur Klärung standardmäßig nicht ausgeliefert |
| Panomitys eigene Regeln | der Kern des Produkts |
Lokale Overlays
Ein Betreiber kann ein lokales Overlay auf einer verifizierten Vendor-Basis aufbauen. Der einzige zulässige Aufbau verifiziert zuerst die vollständige signierte Vendor-Generation mit gepinnten Schlüsseln. Lokale YARA- und Hash-Quellen müssen aus root-eigenen Verzeichnissen stammen, die weder für die Gruppe noch für alle beschreibbar sind; Symlinks und Hardlinks werden zurückgewiesen. Das lokale Manifest ist unsigniert, verweist aber auf die Vendor-Generation und deren Manifest-Digest und erbt deren Ablauf.
Konfiguration
[feeds]
url = "https://feeds.example.invalid/shelltrap"
public_keys = ["/etc/shelltrap/keys/vendor.pub"]
interval = "1h"
keep_generations = 3
corpus_dir = "/var/lib/shelltrap/corpus"
rules_dir = "/etc/shelltrap/rules.d"
hashes_dir = "/etc/shelltrap/hashes.d"
url ist eine Basis-URL; index.json hängt der Client selbst an. Der Timer verwendet interval
mit ±10 % Jitter. Bei leerer url, aber konfigurierten Pins wertet der Timer weiterhin lokale
Regel- und Hash-Overlays neu aus. Health meldet einen nicht konfigurierten Remote-Feed als
feeds: not_configured, und dieser Unterstatus allein macht den Gesamtstatus nicht degradiert —
eine fehlende aktive Generation dagegen schon.
shelltrap feeds list
shelltrap feeds update
shelltrap feeds rollback 20260903T120000Z-0001
Weiter
- Lizenzierung und Aktivierung — warum der Feed nach einem Token fragt
- Konfiguration und Richtlinien
Gekürzt aus dem Shelltrap-Feed-Handbuch, Revision 2026-09-04.