Zero-Server-Side-Browser-Tools: Entwicklung sicherer Werkzeuge mit Vanilla JavaScript

Inhalt
Ein lokales Browserwerkzeug kann Eingaben hashen, auswerten oder umformen, ohne diese Inhalte an einen Anwendungsserver zu übertragen. Der Vorteil ist ein kleinerer Datenfluss: Ein Verarbeitungsendpunkt benötigt die sensiblen Inhalte nicht. Die Seite selbst kann weiterhin aus dem Netz geladen werden; dabei fallen beim Hostingserver Anfragemetadaten an. Die Aussage „lokal verarbeitet“ braucht deshalb einen klaren Geltungsbereich.
Lokale Verarbeitung hat eine Vertrauensgrenze
Die Browser-Sandbox trennt Webinhalte von Teilen des Betriebssystems. Code auf derselben Seite kann trotzdem Eingabefelder lesen. Ein kompromittiertes Skript, unsicher eingefügtes HTML oder eine Browsererweiterung mit passenden Rechten kann die Vertraulichkeit beeinträchtigen. Vanilla JavaScript bezeichnet Code ohne Framework und ist keine Sicherheitsgarantie.
Wenige Abhängigkeiten, HTTPS-Auslieferung, geprüfter Quellcode und der Verzicht auf Analytics oder Sitzungsaufzeichnungen im Eingabebereich verringern Risiken. Eingaben gehören nicht in URLs, Anwendungsprotokolle oder Fehlertelemetrie. Beliebiger Text wird über textContent oder das value eines Eingabefeldes ausgegeben, nicht über innerHTML.

Die vorgesehenen Bytes hashen
TextEncoder kodiert JavaScript-Text als UTF-8-Bytes. TextDecoder wandelt Bytes einer ausgewählten Kodierung zurück in Text. Auch diese Vorgänge benötigen Speicher und Rechenzeit. crypto.subtle.digest() liefert ein Promise; vorbereitende Textumwandlungen und Schleifen können den Hauptthread trotzdem beschäftigen. Hardwarebeschleunigung und fehlende Latenz sind nicht garantiert.
Das Beispiel berechnet SHA-256 über die UTF-8-Darstellung, ohne Leerzeichen zu entfernen oder Großbuchstaben zu verändern. Die Grenze von einer Million UTF-16-Codeeinheiten ist eine beispielhafte Anwendungsgrenze, keine Browsergarantie und keine Byte-Grenze. Eine aufrufende Oberfläche muss abgelehnte Eingaben und Fehler verständlich anzeigen.
async function sha256Text(text) {
if (typeof text !== 'string') throw new TypeError('Expected text');
if (text.length > 1_000_000) throw new RangeError('Input too large');
if (!globalThis.isSecureContext || !globalThis.crypto?.subtle) {
throw new Error('Web Crypto requires a supported secure context');
}
const bytes = new TextEncoder().encode(text);
const digest = await crypto.subtle.digest('SHA-256', bytes);
return Array.from(new Uint8Array(digest),
byte => byte.toString(16).padStart(2, '0')).join('');
}
Für eine Dateiprüfsumme sind die ursprünglichen Datei-Bytes maßgeblich, nicht erneut dekodierter und kodierter Text. digest() benötigt die vollständige Eingabe im Speicher und unterstützt kein schrittweises Streaming. Sehr große Dateien erfordern eine andere geprüfte Implementierung und gemessene Ressourcengrenzen. SHA-256 allein ist weder Verschlüsselung noch ein geeignetes Verfahren zur Passwortspeicherung. Vorhersagbare personenbezogene Angaben werden durch einen Hash nicht automatisch anonym.
CSP begrenzt bestimmte Übertragungswege
connect-src 'self' erlaubt Skriptverbindungen zur eigenen Origin. connect-src 'none' blockiert die von dieser Direktive erfassten Verbindungs-APIs, etwa fetch, WebSocket und Beacons. Für Bilder, Formulare, Frames und Skriptdateien gelten eigene Regeln. Die Richtlinie eines lokalen Werkzeugs muss auch diese Wege berücksichtigen und ausführbaren Code eng begrenzen.
CSP wird im Browser durchgesetzt und bietet eine zusätzliche Schutzschicht, ist aber keine allgemeine Netzwerk-Firewall und kein mathematischer Ausschluss von Datenabfluss. Navigation und erlaubte Ressourcenabrufe benötigen eine eigene Betrachtung. Auch selbst gehostete Skripte können kompromittiert sein. Eine durchgesetzte Richtlinie muss geprüft werden; Report-Only meldet Verstöße, blockiert aber nicht.
Workers verbessern die Reaktionsfähigkeit, nicht die Geheimhaltung
Ein Web Worker kann aufwendige Berechnungen vom UI-Thread trennen. Direkter DOM-Zugriff fehlt im Worker, doch die Seite übergibt Eingabe und empfängt Ergebnis. Schädlicher Seitencode kann deshalb an beiden Übergabepunkten mitlesen. Auch Workers können Netzwerkanfragen ausführen.
Eine getrennte Workerdatei benötigt den passenden CSP-Antwortheader für den eigenen Ausführungskontext. worker-src der Seite steuert das Laden des Workers, nicht automatisch dessen spätere Verbindungen. Blob-Workers erben die Richtlinie des Erzeugers und benötigen eine passende Ladefreigabe. Eine separate Datei erleichtert die Prüfung; eine Prüfsumme allein belegt jedoch kein netzwerkfreies Verhalten.
Nachweise und verbleibende Grenzen
Eine sinnvolle Prüfung umfasst Laden, Eingabe, Verarbeitung, Kopieren oder Download, Fehlerfälle und Leeren. Zur Netzwerkprüfung gehören Workers und gegebenenfalls aktive Service Workers. Ein Offline-Durchlauf nach dem Laden belegt den geprüften Stand und Ablauf, nicht jede spätere Version. Testumgebungen mit gesperrtem Netzwerk liefern einen zusätzlichen Nachweis.
Leere Felder und verworfene Referenzen verringern versehentliche Wiederverwendung. JavaScript kann aber keine forensische Löschung sämtlicher Kopien im Browser- oder Betriebssystemspeicher zusichern. Zwischenablage, Downloads und absichtlich gespeicherte Daten können einen Tab überdauern. Unnötige Speicherung zu vermeiden ist belastbarer als vollständige Löschung beim Schließen zu versprechen.
Fragen und Antworten
Gilt der sichere Kontext auch bei lokaler Entwicklung?
crypto.subtle benötigt einen unterstützten sicheren Kontext. HTTPS und normale Entwicklung über localhost sind geeignet. Eine einfache HTTP-Adresse im privaten LAN gilt normalerweise nicht als sicherer Kontext. Das Beispiel prüft sowohl den Kontext als auch die Verfügbarkeit der API und meldet fehlende Unterstützung.
Beweist ein leerer Netzwerk-Reiter die Vertraulichkeit?
Nur der beobachtete Ablauf ist damit dokumentiert. Ein ergänzender Offline-Test, eine geprüfte durchgesetzte CSP und Kontrolle der ausgelieferten Abhängigkeiten stärken den Nachweis. Ein einzelner Test ersetzt keine Prüfung späterer Änderungen.
Quellen
- MDN Web Docs
- OWASP Top 10
- Web Crypto digest: secure context, Promise, no streaming
- TextEncoder: UTF-8 encoding
- TextDecoder: byte decoding
- Workers: communication and CSP
- CSP connect-src scope
- Secure contexts and localhost
- Content Security Policy Level 3
- OWASP: safe DOM output
- JavaScript memory management
- OWASP: password hashing