Default-Deny-Grenze

Wenn Code entscheidet, ob etwas eine Vertrauensgrenze passieren darf: liefert der unbekannte Fall den sicheren oder den bequemen Wert? Ziel: die Entscheidung so bauen, dass Vergesslichkeit in Richtung „verweigern” fehlschlägt, nicht in Richtung „durchlassen”.

Merkmal

Eine Aufzählung des nachweislich Erlaubten, und ein Rückfall, der verweigert:

  • Der switch/die Schleife listet nur, was geprüft wurde.
  • Der Default-Zweig gibt false / err zurück — nie „ist schon okay”.
  • Keine Normalisierung vor dem Vergleich. Kein Trimmen, kein Kleinschreiben. Wer etwas anderes schickt als die Liste, meint etwas anderes.
  • Neue Fälle müssen aktiv eingetragen werden. Wer einen vergisst, bekommt Verweigerung — nicht ein Leck.

Das Gegenteil (Deny-List / Default-Allow) verlagert die Beweislast: man müsste alles Gefährliche kennen. Man kennt es nie vollständig.

Belegte Fälle (bridgekit)

GrenzeRichtungStelleRückfall bei Unbekanntem
Scrubber: darf ein OBX-Wert ungemaskiert raus?ausgehend (→ Claude-API)internal/scrubber/scrubber.go · obxWertUnbedenklichreturn false → wird maskiert
Aktionen: darf ein Kommando laufen?eingehend (Request → Shell)internal/dienste/aktionen.go · findeAktionreturn aktion{}, false → ErrUnbekannteAktion, 400, nichts läuft

Beide sichern entgegengesetzte Richtungen derselben Prozessgrenze. bridgekit spricht mit genau zwei Außenwelten (Claude-API, docker) — jede hat ein Default-Deny-Tor. Zusammen ergeben sie eine geschlossene Hülle.

Das eigentliche Bedrohungsmodell

Beide Stellen benennen im Kommentar nicht den Angreifer, sondern die eigene Bequemlichkeit von morgen (ADR-008). Der Header von aktionen.go sagt es wörtlich: wer „nur schnell den Namen durchreichen” will, baut eine Remote-Shell auf 127.0.0.1. Die Struktur ist genau das, was diese Abkürzung verhindert.

Diagnosefrage für fremden Code: Was passiert, wenn ich einen Fall vergesse — kommt eine Verweigerung oder ein Leck?

Wachpunkt: eine Default-Deny-Grenze kann von woanders aufgeweicht werden

Scrubber.Maskiere verlangt zuerst, dass hl7.Parse die Nachricht akzeptiert. Die Fail-closed-Eigenschaft des Scrubbers hängt damit an der Strenge eines fremden Pakets, das davon nichts weiß.

Wie eng die Abhängigkeit wirklich ist, war nur per Mutation zu klären, nicht per Lesen. Der Scrubber hat ein zweites Tor (trennerAus), das drei der vier Parse-Ablehnungen unabhängig wiederholt. Tragend bleibt eine einzige Prüfung: fehlt MSH-2 (Kodierzeichen), lehnt nur Parse ab. Details und Belege: ADR-009.

Verallgemeinert, und das ist die eigentliche Lehre — sie hat zwei Stufen, weil ich in beide Fallen getappt bin:

  • Eine Default-Deny-Grenze, die ihre Ablehnung von einem anderen Modul bezieht, ist nur so streng wie dieses Modul. Diese Abhängigkeit gehört benannt — sonst weicht sie jemand auf, der von der Grenze nichts weiß.
  • Welche Prüfung tragend ist, lässt sich nicht durch Hinschauen entscheiden. Redundante Tore verschleiern es. Die plausible Erzählung („der Scrubber hängt am Parser”) war zu grob; erst die Mutation — jede Prüfung einzeln deaktivieren, schauen welcher Test rot wird — trennt tragend von doppelt gesichert.
  • Und dann noch einmal: Auch die Begründung warum eine Prüfung trägt, ist eine Behauptung und braucht ihre eigene Gegenprobe. Zweite ADR-Fassung: „ohne MSH-2 zerlegt der Scrubber mit falschen Feldgrenzen und ein Name leckt.” Klang zwingend. War falsch — trennerAus fällt auf ^/~ zurück, und das sind die Standardtrenner, der Name wird maskiert. Der echte Wert der Prüfung ist bescheidener: fail-closed gegenüber kaputter Eingabe, der Scrubber muss nie raten.

Ein Mechanismus, den man sich überzeugend erzählen kann, ist damit noch nicht ausgeführt worden. Die Gegenprobe gehört an die Behauptung, nicht nur an den Test.

Diagnose-Rezept

  1. Grenze finden: Wo entscheidet Code über Passieren/Verweigern? Liefert der unbekannte Fall false?
  2. Fremde Abhängigkeiten der Verweigerung auflisten (fremder Parser, fremde Validierung, fremde Liste).
  3. Jede einzeln kaputtmachen und den Testlauf beobachten. Was rot wird, ist tragend und gehört in ein ADR. Was grün bleibt, ist Verteidigung in der Tiefe — und darf nicht als Schutz verbucht werden.
  • Sicherheit der Aussage: [x] Fakt [ ] Hypothese [ ] Spekulation (Beide Default-Deny-Fälle am Quelltext verifiziert; die tragende Prüfung der Parser→Scrubber-Kopplung per Mutations-Gegenprobe isoliert, siehe ADR-009.)