Zum Hauptinhalt springen

Datenschutz und Sicherheit

MSK Paste ist von Grund auf auf Datenschutz gebaut. Diese Seite erklärt genau, was beim Anlegen und Ansehen eines Pastes gespeichert wird und was nicht.


Was gespeichert wird​

Zu jedem angelegten Paste enthält die Datenbankzeile:

SpalteZweck
paste_idDie öffentliche Kurz-ID, etwa X7q9bA2k
titleOptionaler Titel, nur wenn du einen angegeben hast
contentDer Text des Pastes
languageDie gewählte Sprache für die Syntaxhervorhebung
password_hashbcrypt-Hash (Kostenfaktor 12), nur wenn ein Passwort gesetzt wurde
expires_atZeitpunkt, ab dem der Paste nicht mehr erreichbar ist und gelöscht wird
burn_after_readWahrheitswert
view_countAnonymer Zähler, nie mit Betrachtern verknüpft
delete_tokenZufälliger Token mit 64 Zeichen, nur dem Ersteller gezeigt
size_bytesGröße von content in Bytes
created_atZeitpunkt des Anlegens
created_ip_hashHMAC-SHA-256 der IP des Erstellers, ausschließlich für die Ratenbegrenzung, auch für die Tagesgrenze des Formulars. Wird mit dem Paste gelöscht

Mehr nicht. Es gibt keine Tabelle für Aufrufe, keine für Nutzer, keine für Sitzungen und keine Spalte mit einer IP-Adresse im Klartext.

API-Keys für die REST-API liegen in einer eigenen Tabelle, api_keys. Darin stehen nur der scrypt-Hash jedes Keys, ein kurzes Präfix, eine Bezeichnung und wann der Key angelegt, zuletzt benutzt und gesperrt wurde. Der Key selbst wird nie gespeichert.


Was NICHT gespeichert wird​

  • Keine IP-Adressen im Klartext. IPs werden mit HMAC-SHA-256 und einem serverseitigen Geheimnis (IP_HASH_SECRET) gehasht. Ohne das Geheimnis lassen sich die Hashes nicht zurückrechnen.
  • Kein GeoIP, keine Länderabfragen. Die Anwendung fragt nie einen Standortdienst.
  • Keine Analyse. Kein Google Analytics, kein Plausible, kein Fathom, kein Matomo, gar nichts.
  • Keine Tracking-Cookies. Das einzige Cookie von MSK Paste heißt NEXT_LOCALE und merkt sich deine Sprache (de oder en).
  • Ein einziges Skript von Dritten, und nur auf der Seite zum Anlegen. Die Seite mit dem Formular lädt Cloudflare Turnstile als Spamschutz, siehe unten. Seiten, die einen Paste anzeigen, laden nichts von Dritten. Alles andere kommt vom selben Ursprung, Shiki und die Schriften werden beim Bauen mit eingepackt.
  • Kein Referer-Logging auf Anwendungsebene. Apache schreibt möglicherweise übliche Zugriffsprotokolle, das entscheidet der Betreiber.
  • Kein Aufrufverlauf. Der Zähler steigt, aber die Anwendung hat keine Möglichkeit zu wissen, wer einen Paste angesehen hat.

Wie die Ratenbegrenzung ohne IPs funktioniert​

Eine Ratenbegrenzung muss „denselben Client" erkennen, ohne identifizierende Daten zu speichern. Der Ablauf:

  1. Die IP des Clients aus X-Real-IP nehmen. Den Header setzt Apache aus der Verbindung, er ersetzt alles, was ein Client selbst mitschickt. Fehlt er, gilt der letzte Eintrag in X-Forwarded-For, den Apache angehängt hat. CF-Connecting-IP und der erste Eintrag in X-Forwarded-For werden nie benutzt, weil der Client sie selbst schreibt und sich damit für jede Anfrage eine neue Adresse aussuchen könnte.
  2. HMAC-SHA-256(ip, IP_HASH_SECRET) berechnen.
  3. Den Hash in einem rein im Speicher gehaltenen gleitenden Fenster der letzten Anfragen ablegen. Das ist die Grenze pro Stunde.

Die Tagesgrenze des Formulars (20 Pastes und 5 MB je 24 Stunden) zählt die Pastes, die mit demselben created_ip_hash gespeichert sind. Der Hash wird zusammen mit dem Paste gelöscht.

Weil das Geheimnis je Installation erzeugt wird (openssl rand -hex 32), kann selbst jemand mit vollem Datenbankzugriff die Hashes nicht in IP-Adressen zurückverwandeln. Ohne das Geheimnis lässt sich keine Rainbow Table dafür berechnen.

Der Speicher-Eimer der Grenze pro Stunde wird bei jedem Neustart geleert, dieser Teil der Ratenbegrenzung ist also kurzlebig. Anfragen mit API-Key werden je Key gezählt, nicht je IP-Adresse.


Spamschutz (Cloudflare Turnstile)​

Die Seite mit dem Formular zum Anlegen lädt Cloudflare Turnstile von challenges.cloudflare.com. Turnstile prüft, ob ein Mensch das Formular abschickt. Es ist das einzige Skript von Dritten in MSK Paste, und auf Seiten, die einen Paste anzeigen, wird es nicht geladen.

Beim Laden der Seite zum Anlegen verbindet sich dein Browser mit Cloudflare, Cloudflare erhält dabei deine IP-Adresse und Angaben zu deinem Browser. Schickst du das Formular ab, reicht MSK Paste das Turnstile-Token und deine IP-Adresse an Cloudflare weiter, um die Prüfung zu bestätigen.

  • Anbieter: Cloudflare, Inc., USA
  • Rechtsgrundlage: Art. 6 Abs. 1 lit. f DSGVO, das berechtigte Interesse, den Dienst frei von Spam und Missbrauch zu halten
  • Übermittlung in die USA: Cloudflare ist nach dem EU-US Data Privacy Framework zertifiziert. Zusätzlich gelten Standardvertragsklauseln.

Passwortschutz​

Passwörter werden vor dem Speichern mit bcrypt bei Kostenfaktor 12 gehasht. Das Klartextpasswort landet nie in der Datenbank. Beim Prüfen wird das eingegebene Passwort gegen den Hash gehalten. Fehlversuche zählen nicht im Aufrufzähler mit und lösen kein Löschen nach dem Lesen aus.

info

Der Inhalt selbst liegt unverschlüsselt. Das Passwort schützt den Zugriff, aber wer die Datenbank verwaltet, könnte den Inhalt technisch direkt lesen. Für wirklich sensible Geheimnisse behandle MSK Paste als nicht vertrauenswürdig und verschlüssle den Inhalt vorher selbst, etwa mit age oder gpg.


Nach dem Lesen löschen​

Ist die Funktion aktiv, löst der erste erfolgreiche Aufruf ein atomares SQL-DELETE im selben Durchgang wie das Lesen aus. Das bedeutet:

  • Zwei gleichzeitige Betrachter können den Inhalt nicht beide sehen. Nur einer gewinnt das Rennen, der andere sieht den Zustand „verbrannt".
  • Nach dem Löschen ist die Zeile weg. Kein Ausblenden, keine Wiederherstellung.
  • Selbst der Betreiber, also du beim Selbsthosten, kommt danach nicht mehr an den Inhalt.

Ablauf und Aufräumen​

Jeder Paste hat einen Zeitpunkt expires_at. Die Ansicht prüft ihn bei jeder Anfrage und zeigt den abgelaufenen Zustand, sobald er überschritten ist.

Ein nächtlicher Cronjob (scripts/cleanup.ts) führt DELETE FROM pastes WHERE expires_at < NOW() aus und entfernt abgelaufene Zeilen tatsächlich. Standardmäßig läuft er um 03:30 Uhr Serverzeit.

Soll ein Paste sofort beim Ablauf verschwinden statt erst nachts, lass das Aufräumskript einfach häufiger laufen, etwa stündlich.


Datenbank-Backups​

Das beiliegende Skript backup.sh legt täglich einen SQL-Dump an (standardmäßig um 03:00 Uhr) und hält ihn 14 Tage vor. Backups enthalten alles aus der Datenbank, also auch gehashte IPs und Passwort-Hashes, aber keine IPs und keine Passwörter im Klartext.

Sie sicher aufzubewahren, ist deine Aufgabe. Denk an:

  • den Dump verschlüsseln (gpg --symmetric)
  • ihn außer Haus schaffen (rsync, S3 mit SSE, restic nach Backblaze und Ähnliches)
  • die Dateirechte des Backup-Verzeichnisses einschränken

CSP und Sicherheits-Header​

MSK Paste setzt bei jeder Antwort eine strikte Content Security Policy und weitere Header, und zwar in proxy.ts:

Content-Security-Policy: default-src 'none'; script-src 'self' 'nonce-...' 'strict-dynamic' https://challenges.cloudflare.com; ...
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
X-Frame-Options: DENY
Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=(), usb=()

Die einzige fremde Quelle, die die Policy zulässt, ist https://challenges.cloudflare.com, für das Skript von Turnstile, seinen Frame und seine Anfragen.

Der Apache-vHost erzwingt zusätzlich HTTPS, OCSP-Stapling und zeitgemäße TLS-Verfahren.


Eine Sicherheitslücke melden​

Du hast ein Sicherheitsproblem gefunden? Bitte melde es über:

Mach für Sicherheitsprobleme bitte kein öffentliches GitHub-Issue auf, damit wir die Lücke schließen und verantwortungsvoll offenlegen können.


Quelloffen​

MSK Paste steht unter AGPL-3.0-or-later. Du kannst jede Zeile des Quellcodes auf GitHub nachlesen und diese Angaben selbst überprüfen. Änderst du den Code und betreibst die geänderte Fassung als Netzwerkdienst, verlangt die AGPL, dass du deine Änderungen veröffentlichst.