Sicherheit und Aufbau
Eine geheime Abstimmung steht und fällt mit dem Vertrauen in die Technik. Deshalb beschreiben wir hier offen, wie das System aufgebaut ist, was es schützt – und was nicht.
Das Grundprinzip: Trennung durch Aufbau
Zwei Dinge dürfen nie zusammenkommen: wer abstimmen darf und was abgestimmt wurde. Beides liegt in getrennten Tabellen ohne jede Verbindung.
Die Einladung weiß nur, dass eine Adresse bereits abgestimmt hat (ja oder nein). Die Stimme kennt nur die Auswahl und eine Zufalls-ID. Es gibt keinen Fremdschlüssel, keine gemeinsame ID und keinen Zeitstempel, über den sich beide wieder zusammenführen ließen. Auch der Organisator und Administratoren mit Datenbankzugriff (Abfragen, Datenbank-Export) können Stimmen daher keiner Person zuordnen.
Was gespeichert wird
| Daten | Inhalt | Aufbewahrung |
|---|---|---|
| Organisation | Name der Loge, E-Mail-Adresse für den Login | bis zur Löschung der Organisation |
| Abstimmung | Titel, Zeitraum, Optionen, Anzahl je Option, Beteiligung | bis du sie löschst |
| Einladung | E-Mail-Adresse, Versandstatus, ob abgestimmt wurde (ja/nein), Hash des Links | 30 Tage nach Abschluss oder Abbruch, dann gelöscht |
| Stimme | Gewählte Option, Zufalls-ID – ohne Zeitstempel und ohne Personenbezug | bleibt für das Ergebnis; sofort gelöscht bei Abbruch oder zu geringer Beteiligung |
| Empfängerliste | zuletzt verwendete Adressen deiner Loge | bis du sie löschst |
| Login-Links | Hash, Ablaufzeit | kurz gültig, nach Ablauf gelöscht |
Links und Tokens
Jeder Link enthält ein zufälliges Token mit 256 Bit Entropie. Gespeichert wird nur dessen SHA-256-Hash, das Token selbst existiert nur in der E-Mail. Ein Datenbankauszug reicht deshalb nicht, um in fremdem Namen abzustimmen.
Login-Links werden erst durch einen Klick auf einen Button eingelöst, nicht schon beim bloßen Aufruf. So verbrauchen Link-Scanner von Mailsystemen sie nicht versehentlich.
Einmaligkeit und Gleichzeitigkeit
Beim Absenden wird die Einladung in der Datenbank gesperrt. Doppelklicks oder doppelte Aufrufe zählen genau einmal. Stimme und „hat abgestimmt“-Markierung werden in einer einzigen Transaktion geschrieben: entweder beides oder nichts.
Keine Zeitstempel, keine Reihenfolge
Weder bei Stimmen noch bei Einladungen wird festgehalten, wann abgestimmt wurde. Die Liste der Beteiligten ist alphabetisch sortiert, die optionale Stimmenliste nach Zufalls-ID. So lässt sich auch über Zeitnähe oder Einfügereihenfolge nichts zuordnen.
Auch die Datenbank selbst vergisst die Reihenfolge
Datenbanken merken sich intern, in welcher Transaktion und an welcher Stelle eine Zeile geschrieben wurde (bei PostgreSQL die Systemspalten xmin und ctid). Weil Stimme und „hat abgestimmt“-Markierung gemeinsam gespeichert werden, ließen sich beide darüber verbinden. Deshalb schreibt jede Stimmabgabe alle Stimmen und Einladungen der Abstimmung in zufälliger Reihenfolge neu: Danach tragen alle Zeilen dieselbe Transaktions-ID, und ihre Reihenfolge ist zufällig. Ein automatischer Test prüft genau das.
Logging
Die Anwendung schreibt keine Zugriffsprotokolle, weil die Links geheime Tokens enthalten. Der vorgeschaltete Webserver ist so zu konfigurieren, dass er die Pfade /v/ und /auth/ ebenfalls nicht protokolliert. Seiten werden mit no-store und ohne Referrer ausgeliefert.
Mindestbeteiligung
Eine Abstimmung braucht mindestens drei Empfänger. Ein Ergebnis wird nur angezeigt, wenn mindestens drei Stimmen abgegeben wurden. Andernfalls erscheint kein Ergebnis, und die Stimmen werden gelöscht.
Kein Zwischenstand, kein Nachladen
Das Ergebnis erscheint erst nach Abschluss. Abbruch zeigt nie ein Ergebnis und löscht die Stimmen. Nach Abschluss lassen sich weder Frist verlängern noch Wähler nachladen – sonst ließe sich eine einzelne Stimme aus dem Unterschied zweier Zwischenstände ableiten.
Login ohne Passwort
Organisatoren melden sich per Einmal-Link an, der 15 Minuten gültig ist. Es gibt keine Passwörter, die gestohlen werden können. Anfragen sind pro Adresse und IP begrenzt, die Antwort verrät nicht, ob eine Adresse existiert. Sitzungen laufen über signierte, nur per HTTP übertragene Cookies mit SameSite=Lax. „Abmelden“ beendet serverseitig alle Sitzungen dieses Kontos auf allen Geräten. Formulare werden nur angenommen, wenn sie von dieser Seite selbst stammen; so kann keine fremde Webseite Aktionen in deinem Namen auslösen oder dir ein fremdes Konto unterschieben.
Browser-Härtung
Die Seiten laden keinerlei Skripte, Schriften oder Bilder von Dritten. Eine strikte Content-Security-Policy erlaubt nur eigene Ressourcen. Es gibt keine Tracker und keine Analyse-Dienste.
Betrieb
Der Container läuft ohne Root-Rechte. Das Datenbankschema wird über versionierte Migrationen verwaltet. Eine automatische Testsuite prüft die Anonymitäts-Eigenschaften bei jeder Änderung, etwa dass bei Stimmen kein Zeitstempel und keine Verbindung zu Einladungen existiert.
Optional: Nachprüfbarkeit
Auf Wunsch der Loge erhalten Wähler einen Quittungscode. Nach Abschluss sehen alle Eingeladenen über ihren persönlichen Link eine Liste aller Codes mit der gezählten Auswahl, in zufälliger Reihenfolge. So kann jede Person selbst prüfen, dass die eigene Stimme enthalten ist – ohne den Code jemandem zeigen zu müssen. Standardmäßig ist das aus.
Schutz vor Missbrauch
Neue Logen arbeiten im Testmodus (höchstens drei Empfänger je Abstimmung und zehn Einladungen pro Tag), bis der Betreiber sie verifiziert hat. Der Server versendet höchstens eine E-Mail pro Sekunde, neue Links für dieselbe Adresse sind begrenzt, und Eingaben haben feste Obergrenzen. Nie bestätigte Registrierungen werden nach 24 Stunden gelöscht.
Cloudflare auf dieser Instanz
Auf dieser Instanz läuft der Datenverkehr über Cloudflare. Die verschlüsselte Verbindung endet dort, Cloudflare könnte also technisch die aufgerufenen Adressen (auch Abstimmungs- und Login-Links) und übermittelte Formulardaten sehen – wie jeder vorgeschaltete Dienst dieser Art. In der Datenbank bleiben Stimme und Person davon unabhängig getrennt. Wer das vermeiden möchte, betreibt die Software selbst ohne vorgeschalteten Dienst.
Die Grenzen – ehrlich benannt
Das System schützt zuverlässig gegen jeden, der nachträglich die Datenbank abfragt oder einen Datenbank-Export (z. B. pg_dump) liest, einschließlich Organisator und Administratoren.
Es schützt nicht gegen jemanden, der den laufenden Server kontrolliert, den Programmcode verändert oder alle Server- und Proxy-Logs mitliest: Der Server sieht beim Abstimmen kurz Link und Auswahl im selben Vorgang. Dasselbe gilt für jemanden mit Zugriff auf die rohen Datenbankdateien, Festplatten-Snapshots oder das Transaktionsprotokoll (WAL): Dort können alte Zeilenversionen noch eine Weile lesbar sein. Betreibe eine Instanz deshalb in der Hand einer Stelle, der deine Mitglieder vertrauen – oder selbst.
Bei einstimmigen Ergebnissen ist die Wahl jedes Einzelnen logischerweise bekannt, und eine Person mit mehreren E-Mail-Adressen kann mehrfach eingeladen werden. Beides lässt sich technisch nicht verhindern.
Der Organisator bestimmt die Empfänger. Wer eine Abstimmung anlegt, sieht, wer bereits abgestimmt hat, und kann eigene Adressen einladen. Damit lässt sich die Mindestzahl von drei Stimmen mit eigenen Stimmen auffüllen und so die Stimme einer einzelnen Person erkennen. Technisch verhindern lässt sich das nicht; die Software schützt die Anonymität gegenüber der Datenbank, nicht gegenüber einem Organisator, der die Empfängerliste manipuliert. Die Loge sollte deshalb Empfängerliste und Beteiligung transparent machen.
Schwachstelle gefunden?
Bitte melde sie vertraulich. Kontaktdaten stehen in der Datei security.txt und im Impressum. Wir bedanken uns und beheben berechtigte Meldungen zügig.
Nachprüfen statt glauben
Der gesamte Quelltext ist einsehbar, die Tests ebenfalls. Siehe Quelltext & Lizenz.