Repository navigation
v0.0.21
Pre-releaseSicherheitsprüfung, alle Gruppen. Eine Migration (00060) kommt mit, sie läuft
beim Start von selbst.
Die Bestätigungsseite einer Bestellung ist nur noch über einen privaten Link
erreichbar. Bisher lag sie unter /bestellung/2026-0001, und die Nummer zählt
hoch: Wer eine Nummer kannte, konnte alle anderen durchprobieren und Namen,
Adressen und Bestelltes lesen. Der Link enthält jetzt eine zufällige Kennung aus
32 Zeichen, die sich nicht erraten lässt. Die Bestellnummer steht weiter auf der
Seite und in den Mails, öffnet aber nichts mehr. Die Mails, die Weiterleitung
nach dem Absenden und die Rückkehr von der Zahlungsseite führen auf den neuen
Link. Ein alter Link mit der Nummer zeigt eine 404-Seite; schon verschickte
Bestätigungsmails sind davon betroffen, und wer sie noch einmal öffnen will,
bekommt den neuen Link vom Betreiber. Bestehende Bestellungen erhalten bei der
Migration ihre Kennung automatisch.
Eine geschützte Startseite fragt jetzt nach dem Passwort. Alle anderen Seiten
taten das schon, die Startseite lieferte ihren Inhalt an jeden aus. Nach der
Eingabe führt der Weg wieder auf die Startseite zurück, und der Inhalt wird wie
bei jeder geschützten Seite nicht von gemeinsamen Zwischenspeichern aufbewahrt.
Das Passwort eines Versandkontos wandert nicht mehr mit zu einem anderen
Server. Wer unter „Versand“ einer Website Server, Port oder Benutzernamen
ändert und das Passwortfeld leer lässt, bekommt jetzt die Meldung, das Passwort
erneut einzugeben, statt dass das gespeicherte Passwort an den neuen Server
geschickt wird. Bleiben alle drei gleich, bleibt das Passwort wie bisher
erhalten.
Eine Zahlungsbestätigung kann eine abgeschlossene Bestellung nicht mehr
überschreiben. Eine Bestellung wird nur noch als bezahlt oder fehlgeschlagen
vermerkt, solange sie offen ist oder ein früherer Versuch fehlgeschlagen war,
und nur, wenn die Zahlungsseite diejenige ist, die zu dieser Bestellung gehört.
Eine von Hand erfasste Rückerstattung bleibt also stehen.
Unterschiedlich geschriebene Hostnamen belegen keinen Platz mehr im
Zwischenspeicher. „Example.COM“, „example.com.“ und „example.com“ sind
dieselbe Adresse und werden einmal gespeichert, und der Speicher hat eine
Obergrenze.
Unsinnig hohe Preise werden abgelehnt. Ein Betrag über einer Milliarde ist
jetzt ein Fehler in der Eingabe, statt in einen kleinen oder negativen Betrag
umzuschlagen.
Plugin-Migrationen dürfen nur noch eigene Tabellen anlegen. Das SQL, das ein
Plugin mitbringt, lief bisher mit allen Rechten auf der ganzen Datenbank. Jetzt
darf es nur Tabellen und Indizes mit dem eigenen Präfix plugin_<Kennung>_
anlegen, ändern und löschen und in sie schreiben; in plugin_store darf es nur
schreiben, wenn es die eigene Kennung nennt. Lesen darf es Seiten, Websites,
Domains und die alten Formularnachrichten, mehr nicht. ATTACH, PRAGMA,
VACUUM, Trigger, Views und jede Berührung der Tabellen des Kerns werden
abgelehnt, bevor etwas ausgeführt wird, mit einer Meldung, die Migration und
Plugin nennt. Das mitgelieferte Kontaktformular ist davon nicht betroffen.
Dateien aus einem Import und Plugin-Dateien werden nicht mehr als Seite
ausgeliefert. Beim Import einer Website zählt, was in der Datei steckt, nicht
was das Archiv behauptet: Es gelten dieselben Typen wie beim Hochladen im
Admin (Bilder, PDF, Video). HTML, Skripte und XML unter einem Bildnamen werden
mit einem Hinweis im Bericht übersprungen, ebenso ein SVG, das etwas von einem
anderen Server lädt; gespeichert wird der erkannte Typ. Dateien, die ein Plugin
unter /plugin-assets/ mitbringt, kommen mit nosniff und einer
Sandbox-Richtlinie heraus, und .html, .svg und .xml werden zum Herunterladen
angeboten statt im Browser geöffnet. Skripte und Stylesheets bleiben für die
Bildschirme des Plugins nutzbar.
Bei weiteren heiklen Aktionen wird das Passwort erneut verlangt. Wie schon
beim Löschen gilt das jetzt auch für: Zwei-Faktor ausschalten, neue
Wiederherstellungscodes, Plugin hochladen, Plugin einschalten, Vorlage
hochladen, Benutzer ändern (etwa die Rolle) und Website importieren. Ist die
Bestätigung älter als 15 Minuten, führt der Knopf zur Bestätigungsseite und von
dort zurück; hochgeladene Dateien müssen danach noch einmal ausgewählt werden.
Konten, die nur über Single Sign-on angelegt wurden und nie ein Passwort
bekommen haben, kommen an diesen Stellen wie beim Löschen nicht weiter, bis
der Betreiber mit holzcloud user passwd eines setzt.
Ein hängender Mailserver blockiert den Postausgang nicht mehr. Bisher galt
die Wartezeit nur für den Verbindungsaufbau; ein Server, der die Verbindung
annahm und dann schwieg, hielt den Versand beliebig lange fest. Jetzt hat die
ganze Sitzung (Begrüßung, Verschlüsselung, Anmeldung, Nachricht) eine
gemeinsame Frist von dem Dreifachen der eingestellten Wartezeit.
SECURITY.md beschreibt die Zahlung richtig. Dort stand, das Programm kenne
keine Zahlung. Das stimmt seit dem Laden mit Payrexx nicht mehr. Der Text sagt
jetzt, was das Programm tut und prüft: Weiterleitung statt Kartendaten, keine
Benachrichtigung wird geglaubt, sondern der Anbieter wird gefragt, und Betrag,
Währung und Zahlungsseite müssen zur Bestellung passen.
Go-Version, Bibliotheken und htmx sind auf dem neuesten Stand. Das Programm
wird mit Go 1.26.8 gebaut (auch das Container-Image und die mitgelieferten
Plugin-Module). Aktualisiert sind golang.org/x/net, golang.org/x/image und
die SQLite-Bibliothek modernc.org/sqlite samt ihrer Laufzeit. Die Prüfung mit
govulncheck findet keine Lücke, die das Programm erreicht. Zwei Meldungen
betreffen Teile, die das Programm nicht aufruft, und hatten noch keine
korrigierte Fassung. Dazu kommt htmx 2.0.11, dessen Prüfsumme gegen die
Angabe der Paketquelle verglichen wurde. Die Schritte zum Bauen des Images
laufen in GitHub Actions jetzt auf festen, geprüften Versionen statt auf
beweglichen Marken. Nach dem Update ist nichts zu tun.
Der Dienst darf unter systemd weniger. Die mitgelieferte Datei
holzcloud.service erlaubt dem Prozess nur noch IPv4, IPv6 und lokale Sockets,
sperrt privilegierte Systemaufrufe und Eingriffe in Ressourcen, verzichtet auf
alle Capabilities (Port 8080 braucht keine), verbirgt fremde Prozesse und
schützt Uhr, Hostnamen und Kernel-Log. Neue Dateien sind nur für den
Dienstbenutzer lesbar. Auf einem bestehenden Server wirkt das erst mit der
neuen Datei: kopieren, sudo systemctl daemon-reload && sudo systemctl restart holzcloud,
danach journalctl -u holzcloud ansehen und mit
systemd-analyze security holzcloud prüfen. Liegt das Datenverzeichnis nicht
unter /opt/holzcloud/data, muss ReadWritePaths angepasst werden; ein Port
unter 1024 braucht CAP_NET_BIND_SERVICE.
What's Changed
- 0.0.21: Sicherheits- und Update-Audit by @holzcloud in #37
Full Changelog: v0.0.20...v0.0.21