Security-Headers automatisiert in E2E-Tests prüfen
AI generated
PASS
expect()
Security-Headers · E2E-Testing
Security-Headers automatisiert in E2E-Tests prüfen
Wie CSP, HSTS und X-Frame-Options als feste Testassertion in die bestehende E2E-Suite wandern, damit eine stille Regression sofort auffällt

Ein HTTP-Security-Header wie die Content-Security-Policy oder der X-Frame-Options-Header wird meist einmalig, oft im Rahmen eines Security-Audits, sorgfältig konfiguriert und danach kaum noch angefasst. Genau diese Ruhe wird zur Falle, sobald ein späteres Refactoring des Webservers, ein neues CDN oder eine geänderte Nginx-Konfiguration den Header versehentlich verkürzt, entfernt oder falsch setzt, denn im normalen Betrieb eines Onlineshops merkt niemand sofort, dass ein Schutzmechanismus lautlos verschwunden ist. Wird die Prüfung der wichtigsten Security-Header stattdessen als feste Assertion in die ohnehin vorhandene End-to-End-Testsuite aufgenommen, fällt eine solche Regression bereits beim nächsten Testlauf auf, lange bevor sie in Produktion zu einem echten Sicherheitsproblem wird.

15 Min. Lesezeit Security-Headers E2E-Testing

1. Warum Security-Header ohne Test lautlos verschwinden

HTTP-Security-Header werden in der Praxis meist an einer Stelle konfiguriert, die weit entfernt vom eigentlichen Anwendungscode liegt, etwa in der Nginx-Konfiguration, im Reverse Proxy, in einem CDN oder in einer Middleware, die separat vom Magento-Kern gepflegt wird. Diese räumliche Trennung zwischen Header-Konfiguration und Anwendungslogik führt dazu, dass ein Header bei einem Infrastruktur-Umbau, einem CDN-Wechsel oder einer schlicht vergessenen Konfigurationszeile verschwinden kann, ohne dass irgendein funktionaler Test der Anwendung dies bemerkt, denn die Seite selbst funktioniert für Käuferinnen und Käufer optisch und funktional weiterhin einwandfrei.

Ohne eine automatisierte Prüfung bleibt die einzige Absicherung ein manueller, meist nur bei Audits durchgeführter Blick in die Antwort-Header, was in der Praxis bedeutet, dass zwischen zwei solchen manuellen Prüfungen Monate vergehen können, in denen ein fehlender Header unentdeckt bleibt. Ein automatisierter Test, der bei jedem Deployment oder zumindest täglich in der CI-Pipeline läuft, schließt genau diese Lücke, indem er die Header-Präsenz und den Header-Inhalt bei jeder Ausführung neu und zuverlässig überprüft, unabhängig davon, ob sich jemand im Team aktiv daran erinnert.

Besonders kritisch ist dieses Risiko für einen Onlineshop, da Kundendaten, Zahlungsinformationen und Sessions direkt vom Schutzniveau dieser Header abhängen: Eine fehlende oder zu lax konfigurierte Content-Security-Policy öffnet etwa Cross-Site-Scripting-Angriffen Tür und Tor, während ein fehlender HSTS-Header einen Downgrade auf unverschlüsseltes HTTP erleichtert, zwei Szenarien, die sich beide durch einen einfachen, wiederholbaren Test zuverlässig ausschliessen lassen.

2. Welche Header eine feste Testassertion verdienen

Nicht jeder theoretisch mögliche Security-Header muss in jedem Testlauf einzeln geprüft werden, aber eine kleine Kerngruppe hat sich in der Praxis als besonders prüfungswürdig etabliert: die Content-Security-Policy (CSP) als zentrale Verteidigung gegen Cross-Site-Scripting, der Strict-Transport-Security-Header (HSTS) gegen Protokoll-Downgrades, X-Frame-Options beziehungsweise die entsprechende CSP-Direktive frame-ancestors gegen Clickjacking, sowie X-Content-Type-Options gegen MIME-Sniffing-Angriffe.

Für jeden dieser Header lohnt sich nicht nur die reine Präsenzprüfung, sondern auch eine inhaltliche Prüfung der konkreten Direktiven, denn ein vorhandener, aber inhaltlich zu lax konfigurierter Header bietet kaum mehr Schutz als ein fehlender Header. Eine CSP mit der Direktive script-src * etwa erfüllt zwar formal die Anforderung, einen CSP-Header zu setzen, verhindert aber praktisch keinen einzigen Cross-Site-Scripting-Angriff, weshalb der Test die tatsächliche Direktive und nicht nur das blosse Vorhandensein des Headers prüfen sollte.

3. Praktisches Beispiel mit Cypress

In Cypress lässt sich der Zugriff auf die tatsächlichen Response-Header über cy.request() realisieren, da ein regulärer cy.visit()-Aufruf die Header nicht direkt zurückgibt, sondern lediglich die gerenderte Seite lädt. Der folgende Test prüft für die Magento-Checkout-Seite exemplarisch mehrere Header in einer gemeinsamen, klar strukturierten Testfunktion.


describe('Security-Header auf der Checkout-Seite', () => {
  it('setzt CSP, HSTS und X-Frame-Options korrekt', () => {
    cy.request('/checkout').then((response) => {
      const headers = response.headers;

      expect(headers).to.have.property('content-security-policy');
      expect(headers['content-security-policy']).to.include("default-src 'self'");
      expect(headers['content-security-policy']).to.not.include('script-src *');

      expect(headers).to.have.property('strict-transport-security');
      expect(headers['strict-transport-security']).to.include('max-age=');
      expect(headers['strict-transport-security']).to.include('includeSubDomains');

      expect(headers).to.have.property('x-frame-options');
      expect(headers['x-frame-options']).to.eq('SAMEORIGIN');

      expect(headers).to.have.property('x-content-type-options');
      expect(headers['x-content-type-options']).to.eq('nosniff');
    });
  });
});

4. Dasselbe Vorgehen mit Playwright

Playwright erlaubt den Zugriff auf Response-Header sowohl über page.goto(), das ein Response-Objekt zurückgibt, als auch über die eigenständige Request-API, ohne dass dafür ein vollständiges Browser-Rendering nötig wäre, was den Test spürbar beschleunigt, wenn ausschliesslich Header und keine sichtbaren Inhalte geprüft werden sollen.


import { test, expect } from '@playwright/test';

test('Startseite liefert erwartete Security-Header', async ({ request }) => {
  const response = await request.get('/');
  const headers = response.headers();

  expect(headers['content-security-policy']).toContain("object-src 'none'");
  expect(headers['x-frame-options'] ?? headers['content-security-policy']).toBeTruthy();
  expect(headers['referrer-policy']).toBe('strict-origin-when-cross-origin');
  expect(response.status()).toBe(200);
});

5. Umgang mit CSP im Report-Only-Modus

Viele Teams führen eine neue oder verschärfte Content-Security-Policy zunächst im Report-Only-Modus über den Header Content-Security-Policy-Report-Only ein, bei dem Verstösse zwar protokolliert, aber nicht tatsächlich blockiert werden, um vor der endgültigen Aktivierung ungewollte Nebenwirkungen im echten Betrieb sicher beobachten zu können, ohne dabei bereits Funktionalität für echte Käuferinnen und Käufer zu gefährden.

Ein Testfall für diese Übergangsphase sollte klar zwischen beiden Headernamen unterscheiden und je nach aktuellem Projektstatus explizit prüfen, welcher der beiden gesetzt ist, damit später beim geplanten Umschalten von Report-Only auf den tatsächlich erzwingenden Header bewusst auch der zugehörige Test angepasst wird, statt dass die Testsuite unbemerkt weiterhin nur den laxeren Report-Only-Header validiert, obwohl der Header in der Zwischenzeit auf den strengeren, erzwingenden Modus umgestellt wurde.

6. Unterschiedliche Header je Seitentyp berücksichtigen

In einem Magento-Shop unterscheiden sich die tatsächlich notwendigen Header teils je nach Seitentyp: Eine eingebettete PayPal- oder Klarna-Zahlungsseite benötigt unter Umständen gezielt gelockerte frame-src- oder connect-src-Direktiven in der CSP, während die übrige Shopseite deutlich restriktiver konfiguriert sein sollte, weshalb ein einzelner, pauschaler Header-Test für die gesamte Domain die tatsächliche Realität oft nicht korrekt abbildet.

Sinnvoller ist deshalb ein kleines Set gezielter Testfälle je relevantem Seitentyp, etwa je ein eigener Test für Kategorieseite, Produktseite, Warenkorb, Checkout und Kundenkonto, wobei jeder Testfall die für genau diesen Seitentyp erwarteten, spezifischen Header-Direktiven prüft, statt eine einzige, generische Erwartung auf die gesamte Shop-Domain zu projizieren, die den unterschiedlichen tatsächlichen Anforderungen der einzelnen Seitentypen nicht gerecht wird.

Ein weiterer, in der Praxis leicht übersehener Sonderfall betrifft eingebettete Hilfe- oder Support-Widgets von Drittanbietern, die auf vielen Kundenkonto-Seiten eingebunden sind und ebenfalls eigene, oft grosszügigere Direktiven in der Content-Security-Policy benötigen, weshalb sich ein isolierter Testfall gerade für diese Seite lohnt, um sicherzustellen, dass die dort notwendigen Lockerungen nicht versehentlich auf andere, deutlich sensiblere Seitentypen wie den Checkout übergreifen, was ein wichtiger, aber oft erst spät im Projektverlauf entdeckter Qualitätsaspekt ist.

7. Integration in die CI-Pipeline

Damit ein fehlender Header tatsächlich frühzeitig auffällt, sollten die Header-Tests nicht nur lokal, sondern als fester Bestandteil der CI-Pipeline bei jedem Pull Request und zusätzlich regelmässig gegen die Produktivumgebung ausgeführt werden, da eine falsch konfigurierte Infrastrukturänderung (etwa am CDN oder Load Balancer) unter Umständen außerhalb des eigentlichen Deployments der Anwendung passiert und dadurch von reinen Pre-Deployment-Tests gar nicht erfasst würde.

Ein separater, täglich laufender Smoke-Test gegen die echte Produktivdomain, unabhängig vom regulären Deployment-Zyklus, schließt diese Lücke zuverlässig, indem er auch Header-Änderungen erkennt, die durch Infrastruktur-Teams außerhalb des eigentlichen Anwendungscodes vorgenommen wurden, etwa im Rahmen einer CDN-Konfigurationsänderung, die vom Entwicklungsteam möglicherweise gar nicht direkt bemerkt wird.

8. Häufige Fallstricke bei Header-Tests

Ein verbreiteter Fehler ist, den Header-Test ausschliesslich gegen die Startseite laufen zu lassen und daraus fälschlich zu schließen, alle übrigen Seiten seien ebenso abgesichert, obwohl unterschiedliche Seitentypen, wie im vorherigen Abschnitt beschrieben, durchaus unterschiedliche Header-Konfigurationen besitzen können, etwa weil eine eingebettete Drittanbieter-Zahlungsseite eine abweichende CSP benötigt.

Ein weiterer häufiger Fallstrick ist eine zu strikte, auf exakte Zeichenkettengleichheit prüfende Assertion für die CSP, obwohl sich die Reihenfolge der einzelnen CSP-Direktiven oder unkritische Zusatzwerte gelegentlich ändern können, ohne dass die eigentliche Schutzwirkung dadurch beeinträchtigt wird. Ein robusterer Test prüft deshalb gezielt, ob bestimmte, sicherheitsrelevante Direktiven enthalten sind, statt die gesamte Zeichenkette exakt und zeichengenau zu vergleichen, was den Test unnötig zerbrechlich gegenüber harmlosen, funktional irrelevanten Änderungen machen würde.

9. Security-Header-Tests im Überblick

Die folgende Tabelle fasst die wichtigsten Header und die jeweils passende Testtiefe zusammen.

Header Schutzziel Empfohlene Testtiefe
Content-Security-Policy Cross-Site-Scripting, Dateninjektion Inhaltliche Direktivenprüfung, kein exakter Stringvergleich
Strict-Transport-Security Protokoll-Downgrade auf HTTP Präsenz plus max-age-Mindestwert prüfen
X-Frame-Options / frame-ancestors Clickjacking Erwarteten Wert pro Seitentyp prüfen
X-Content-Type-Options MIME-Sniffing Reine Präsenz- und Wertprüfung genügt
Referrer-Policy Ungewollter Datenabfluss über Referrer Erwarteten Policy-Wert prüfen

Mironsoft

E2E-Teststrategie, CI-Integration und stabile Testsuiten

Testsuiten, die Bugs finden statt nur rot zu blinken?

Wir prüfen bestehende E2E-Testsuiten auf Flakiness, fehlende Testisolation und ineffiziente CI-Laufzeiten und bauen daraus eine Teststrategie, die tatsächlich Vertrauen schafft statt nur Haken zu setzen.

Test-Audit

Flaky Tests, Testpyramide und Coverage-Lücken systematisch aufdecken.

CI-Optimierung

Parallele Ausführung, Retry-Strategien und schnelle Feedback-Zyklen aufbauen.

Cypress/Playwright-Setup

Robuste E2E-Suiten für Magento-Frontends von Grund auf einrichten.

10. Zusammenfassung

Security-Header-Tests: Das Wichtigste auf einen Blick

Kernidee

Security-Header als feste Assertion in die bestehende E2E-Suite aufnehmen statt nur manuell bei Audits zu prüfen.

Testtiefe

Konkrete Direktiven prüfen, nicht nur die blosse Präsenz eines Headers.

Seitentyp-Bezug

Unterschiedliche Seitentypen wie Checkout oder eingebettete Zahlungsseiten benötigen eigene Testfälle.

CI-Anbindung

Tests bei jedem Pull Request und zusätzlich täglich gegen Produktion ausführen.

11. FAQ: Security-Header-Tests: Das Wichtigste auf einen Blick

1Warum reicht ein manueller Header-Check bei einem Audit nicht aus?
Zwischen zwei Audits können Monate vergehen, in denen ein fehlender Header unentdeckt bleibt.
2Welche Header sollten zuerst automatisiert getestet werden?
Content-Security-Policy, Strict-Transport-Security, X-Frame-Options und X-Content-Type-Options als Kerngruppe.
3Reicht die reine Präsenzprüfung eines Headers aus?
Nein, eine zu lax konfigurierte CSP wie script-src * bietet kaum Schutz trotz vorhandenem Header.
4Wie teste ich Header ohne vollständiges Browser-Rendering?
Über cy.request() in Cypress oder die Request-API in Playwright, beide liefern Header ohne Rendering.
5Brauchen alle Seitentypen dieselbe CSP?
Nein, eingebettete Zahlungsseiten benötigen oft gelockerte Direktiven gegenüber dem restlichen Shop.
6Wie gehe ich mit Content-Security-Policy-Report-Only um?
Testfälle sollten explizit zwischen Report-Only- und erzwingendem Header unterscheiden und projektaktuell gepflegt werden.
7Wie oft sollten Header-Tests laufen?
Bei jedem Pull Request sowie zusätzlich täglich als Smoke-Test gegen die echte Produktivdomain.
8Warum reicht ein exakter Stringvergleich der CSP nicht?
Weil sich die Reihenfolge der Direktiven ändern kann, ohne dass sich die tatsächliche Schutzwirkung ändert.
9Können Infrastrukturänderungen Header unbemerkt entfernen?
Ja, etwa bei einem CDN- oder Load-Balancer-Wechsel, weshalb tägliche Produktions-Smoke-Tests sinnvoll sind.
10Ersetzt ein Header-Test einen vollständigen Sicherheitsaudit?
Nein, er ergänzt ihn und erkennt Regressionen zwischen zwei Audits frühzeitig.