PWA Security: Die wichtigsten Schutzmassnahmen¶
Progressive Web Apps (PWAs) vereinen das Beste aus Web und Native Apps — Offline-Fähigkeit, Push-Notifications, Installation auf dem Homescreen. Doch mit diesen Möglichkeiten kommen neue Angriffsflächen. Dieser Artikel zeigt die wichtigsten Sicherheitsmassnahmen für produktionsreife PWAs.
HTTPS ist Pflicht¶
Ohne HTTPS keine PWA. Service Worker — das Herzstück jeder PWA — funktionieren ausschliesslich über verschlüsselte Verbindungen. Das ist kein Zufall, sondern bewusster Sicherheitsentscheid: Service Worker können Netzwerk-Requests abfangen und manipulieren. Ohne Verschlüsselung wäre das ein offenes Tor für Man-in-the-Middle-Angriffe.
HTTP Strict Transport Security (HSTS) geht einen Schritt weiter: Der Browser wird angewiesen, ausschliesslich HTTPS-Verbindungen zu akzeptieren — selbst wenn der User manuell http:// eingibt.
Service Worker absichern¶
Service Worker sind mächtig: Sie sitzen zwischen App und Netzwerk, steuern den Cache und ermöglichen Offline-Funktionalität. Genau deshalb verdienen sie besondere Aufmerksamkeit.
Scope einschränken¶
Definiere den Scope so eng wie möglich. Ein Service Worker mit Root-Scope (/) hat Zugriff auf alle Requests der gesamten Domain.
// Zu breit
navigator.serviceWorker.register('/sw.js');
// Besser: nur den App-Pfad
navigator.serviceWorker.register('/app/sw.js', { scope: '/app/' });
Kein sensitiver Content im Cache¶
Der Service Worker Cache ist nicht verschlüsselt. Tokens, Passwörter oder personenbezogene Daten haben dort nichts verloren.
// Im Service Worker: Sensitive Routen nicht cachen
self.addEventListener('fetch', (event) => {
const url = new URL(event.request.url);
// Auth-Endpoints nie cachen
if (url.pathname.startsWith('/api/auth')) {
return; // Network-only
}
event.respondWith(
caches.match(event.request)
.then(response => response || fetch(event.request))
);
});
Updates erzwingen¶
Veraltete Service Worker sind ein Sicherheitsrisiko. Stelle sicher, dass Updates zuverlässig eingespielt werden:
- Cache-Busting: Versioniere deine Service Worker Datei
- skipWaiting(): Aktiviere neue Versionen sofort
- Byte-Vergleich: Browser prüfen automatisch auf Änderungen (auch nur 1 Byte reicht)
Content Security Policy (CSP)¶
Eine CSP ist der Bodyguard deiner PWA. Sie definiert eine Allowlist: Welche Ressourcen darf die App laden, welche nicht?
Content-Security-Policy:
default-src 'self';
script-src 'self';
style-src 'self';
img-src 'self' data: https://trusted-cdn.example.com;
connect-src 'self' https://api.example.com;
frame-ancestors 'none';
Wichtige Regeln:
script-src 'self'— Nur eigene Scripts erlaubenunsafe-inlineundunsafe-evalvermeiden — sie öffnen die Tür für XSSframe-ancestors 'none'— Schutz vor Clickjacking- CSP via HTTP-Header setzen, nicht per Meta-Tag (stärkere Durchsetzung)
Schrittweise einführen
Starte mit Content-Security-Policy-Report-Only, um zu sehen welche Ressourcen blockiert würden, bevor du die Policy scharf schaltest.
Authentifizierung und Session Management¶
Token-Strategie¶
| Token-Typ | Lebensdauer | Speicherort |
|---|---|---|
| Access Token (JWT) | 15–30 Minuten | Memory (Variable) |
| Refresh Token | Tage–Wochen | HttpOnly Cookie |
Niemals Tokens in localStorage oder sessionStorage speichern — beide sind über JavaScript zugänglich und damit anfällig für XSS.
Cookie-Flags¶
- Secure: Nur über HTTPS übertragen
- HttpOnly: Kein Zugriff via JavaScript
- SameSite=Strict: Kein Versand bei Cross-Site Requests (CSRF-Schutz)
WebAuthn¶
Für maximale Sicherheit: Passwortlose Authentifizierung via WebAuthn. Unterstützt Fingerabdruck, Face ID und Hardware-Keys (YubiKey). Phishing-resistent, da die Credentials an die Domain gebunden sind.
Input Validation¶
Validierung auf beiden Seiten:
- Client-Side: Für UX (schnelles Feedback)
- Server-Side: Für Security (die einzige die zählt)
// Server-Side: Parameterized Queries statt String-Concatenation
var orders = await context.Orders
.Where(o => o.Status == status && o.CustomerId == customerId)
.ToListAsync();
Client-Side Validation kann umgangen werden. Jeder Input der den Server erreicht muss als potenziell bösartig behandelt werden: Datentyp, Länge, Format und erlaubte Werte prüfen.
API-Absicherung¶
PWAs kommunizieren intensiv mit APIs. Diese Endpunkte brauchen eigene Schutzmassnahmen:
- Authentifizierung auf jedem Endpoint — kein Endpoint ohne Auth
- Rate Limiting — schützt vor Brute-Force und DDoS
- CORS restriktiv konfigurieren — spezifische Domains statt
*-Wildcards
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Credentials: true
Kein Wildcard mit Credentials
Access-Control-Allow-Origin: * zusammen mit Allow-Credentials: true ist ungültig und wird vom Browser abgelehnt. Definiere immer explizite Origins.
Dependency Management¶
Die Supply Chain ist eine der grössten Angriffsflächen moderner Web-Apps.
npm auditregelmässig ausführen- Automatisierte Security-Scans in die CI/CD Pipeline integrieren
- Dependabot oder Renovate für automatische Updates einsetzen
- Lock-Files (
package-lock.json) immer committen
Checkliste¶
- HTTPS + HSTS konfiguriert
- Service Worker Scope eingeschränkt
- Kein sensitiver Content im Cache
- CSP Header gesetzt (ohne
unsafe-inline/unsafe-eval) - Tokens in Memory oder HttpOnly Cookies
- Input Validation server-seitig
- CORS restriktiv konfiguriert
- Rate Limiting auf API Endpoints
- Dependencies regelmässig aktualisiert
- Security Scans in CI/CD integriert
Fazit¶
PWA Security ist kein einmaliger Aufwand, sondern ein fortlaufender Prozess. Die Kombination aus HTTPS, restriktiver CSP, sicherer Authentifizierung und konsequenter Input Validation bildet ein solides Fundament. Dazu gehört die Disziplin, Dependencies aktuell zu halten und Service Worker Updates zuverlässig auszuliefern.
Die gute Nachricht: Viele dieser Massnahmen sind Standard-Web-Security-Praktiken. Wer seine Web-App bereits sauber absichert, hat bei der PWA-Umsetzung schon die halbe Arbeit erledigt.