Zum Inhalt

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.

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

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 erlauben
  • unsafe-inline und unsafe-eval vermeiden — sie öffnen die Tür für XSS
  • frame-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.

Set-Cookie: session=abc123;
  Secure;
  HttpOnly;
  SameSite=Strict;
  Path=/;
  Max-Age=1800
  • 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 audit regelmä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.