Gegenbuch: verifizierender Leser statt Absichtserklaerung (Pentest R175)
R175-01 (HIGH): Die erste Fassung signierte zwar, prueft aber nie. Sie las ihre Wahrheit per readFileSync aus der lokalen Arbeitsdatei, nirgends gab es ein git verify-commit - das -S war write-only ohne Konsument. Live reproduziert: DB-Tail abgeschnitten und die lokale Ledger-Zeile angepasst -> "OK, Checkpoint beglaubigt", exit 0, kein Alarm. Fix: Wahrheitsquelle ist der signierte Commit-Baum (bevorzugt der Remote-Kopf); jeder Commit mit Gegenbuch-Aenderung muss eine gueltige Signatur tragen; weicht die Arbeitsdatei vom signierten Stand ab, wird abgebrochen; lokale, nie gepushte Commits gelten nicht als beglaubigt; die Signatur des frisch erzeugten Commits wird gegengeprueft. Dazu ein Pruefmodus --check fuer Auditoren. R175-02 (MEDIUM): /checkpoint fuhr je Aufruf ein volles verifyIntegrity (O(n), 0,85 s bei 16k Zeilen) - authentifizierte DoS-Verstaerkung. Gebraucht wurde nur die Siegel-Wurzel. Jetzt Kopf-Hash aus der Kopfzeile, Wurzel aus dem juengsten gueltigen Marker, sealLeafCount statt des teuren Status. R175-03: writeFileSync lief vor dem Commit, eine verwaiste Zeile wurde vom Folgelauf zementiert. Jetzt Ruecknahme bei Fehlschlag, und NOTARY_SIGN=false verlangt zusaetzlich NOTARY_INSECURE_ACK. Verifiziert mit echtem SSH-Signaturschluessel: stilles Waschen -> Alarm; erfundene Zeile -> Alarm; unsignierter Commit -> Alarm; Commit-Fehlschlag -> zurueckgerollt; Reflex-Schalter verweigert; Pruefmodus haengt nichts an. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -97,6 +97,44 @@ isolierte Instanz (keine Multi-Tenancy im Code), Provisioning + Abrechnung
|
||||
|
||||
## ✅ Erledigt
|
||||
|
||||
- [x] **🔏 Gegenbuch: verifizierender Leser statt Absichtserklaerung (Pentest R175)** (2026-08-18)
|
||||
- **R175-01 (HIGH)** – Der Kernsatz des Pentesters: „Append-only allein
|
||||
reicht nicht, es braucht einen verifizierenden Leser.“ Meine erste Fassung
|
||||
signierte zwar, **prüfte aber nie**: Sie las ihre Wahrheit per
|
||||
`readFileSync` aus der lokalen **Arbeitsdatei**, nirgends im Repo gab es
|
||||
ein `git verify-commit`. Das `-S` war write-only ohne Konsument. Live
|
||||
reproduziert: DB-Tail abgeschnitten UND die lokale Ledger-Zeile angepasst →
|
||||
„OK, Checkpoint beglaubigt“, exit 0, kein Alarm. Der gekuerzte Zustand
|
||||
wurde zur neuen Wahrheit.
|
||||
Fix: Wahrheitsquelle ist der **signierte Commit-Baum** (bevorzugt der
|
||||
Remote-Kopf); jeder Commit mit Gegenbuch-Aenderung muss eine gueltige
|
||||
Signatur tragen; weicht die Arbeitsdatei vom signierten Stand ab, wird
|
||||
abgebrochen; lokale, nie gepushte Commits gelten nicht als beglaubigt;
|
||||
die Signatur des frisch erzeugten Commits wird gegengeprueft.
|
||||
Dazu ein **Pruefmodus** `--check` fuer Auditoren (alle Kontrollen, kein
|
||||
Schreibrecht noetig).
|
||||
- **R175-02 (MEDIUM)** – `/checkpoint` fuhr je Aufruf ein volles
|
||||
`verifyIntegrity()` (O(n), gemessen 0,85 s bei 16k Zeilen) – authentifizierte
|
||||
DoS-Verstaerkung. Gebraucht wurde davon nur die Siegel-Wurzel. Jetzt:
|
||||
Kopf-Hash direkt aus der Kopfzeile, Wurzel aus dem juengsten gueltigen
|
||||
Marker (eine Abfrage + Signaturpruefung), plus `sealLeafCount` statt des
|
||||
teuren Status.
|
||||
- **R175-03 (LOW→MED)** – `writeFileSync` lief vor dem Commit: schlug der
|
||||
signierte Commit fehl, blieb eine verwaiste Zeile liegen, die der
|
||||
Folgelauf absorbierte und zementierte. Jetzt Ruecknahme bei Fehlschlag
|
||||
(`git checkout`), und `NOTARY_SIGN=false` verlangt zusaetzlich
|
||||
`NOTARY_INSECURE_ACK=…` – der Reflex „Cron hakt, Signatur abschalten“
|
||||
soll nicht ausreichen.
|
||||
- Verifiziert mit **echtem SSH-Signaturschluessel** gegen eine CRM-Attrappe:
|
||||
stilles Waschen (DB gekuerzt + lokale Datei gebogen) → Alarm statt „OK“;
|
||||
frei erfundene, nie committete Zeile → Alarm; unsignierter Commit in der
|
||||
Historie → Alarm; Commit-Fehlschlag → Datei zurueckgerollt, keine
|
||||
Geisterzeile; `NOTARY_SIGN=false` ohne Bestaetigung → verweigert;
|
||||
Pruefmodus meldet sauber ohne anzuhaengen. Alle Testartefakte geloescht.
|
||||
- Seine Bestaetigungen: Key-Trennung im Deploy haelt (`printenv` im
|
||||
Container zeigt keinen Notar-Schluessel); `audit:read` kann am
|
||||
Checkpoint keine falschen Werte injizieren.
|
||||
|
||||
- [x] **⚖️ Gegenbuch: externe Notarisierung der Audit-Kette** (2026-08-18)
|
||||
- Abschluss der Anker-Kette. Alle bisherigen Schutzebenen liegen in
|
||||
derselben Datenbank, die sie absichern sollen – der Pentest hat das ueber
|
||||
|
||||
Reference in New Issue
Block a user