CORS richtig konfigurieren ohne Sicherheitslücken
OWASP
0x00
Security · CORS · Same-Origin Policy · API-Sicherheit
CORS richtig konfigurieren ohne Sicherheitslücken
Same-Origin Policy, Preflight und sichere Origin-Allowlists

Ein zu freizügig gesetzter Access-Control-Allow-Origin-Header hebt genau den Browserschutz auf, den die Same-Origin Policy eigentlich garantiert. Dieser Artikel erklärt Preflight-Requests, die gefährliche Kombination aus Wildcard und Credentials, Origin-Reflection als häufigsten Fehler und wie eine saubere, server-seitige Allowlist für Magento-APIs hinter CDN und Varnish zuverlässig funktioniert.

16 Min. Lesezeit Access-Control-Allow-Origin · Preflight · Allowlist Magento 2.4.8 · Hyvä Theme · Headless/PWA

1. Same-Origin Policy: der Standardschutz, den CORS bewusst lockert

Die Same-Origin Policy (SOP) ist der Standardschutzmechanismus jedes modernen Browsers und keine optionale Einstellung. Sie verhindert, dass JavaScript auf einer Seite unter origin-a.de per fetch oder XMLHttpRequest die Antwort einer Ressource unter origin-b.de auslesen kann, selbst wenn der Request technisch gesendet und beantwortet wird. Origin bedeutet dabei die exakte Kombination aus Schema, Host und Port: https://shop.example.de und https://api.example.de gelten als zwei unterschiedliche Origins, ebenso http://example.de und https://example.de. Ohne SOP könnte jede bösartige Webseite im Hintergrund Requests an eine Bank-API senden und die Antwort mit den Zugangsdaten des eingeloggten Nutzers direkt auslesen.

Cross-Origin Resource Sharing (CORS) ist kein Ersatz für die Same-Origin Policy, sondern ein bewusst kontrolliertes Ausnahmeverfahren, mit dem ein Server über HTTP-Header signalisiert, welchen fremden Origins er den Zugriff auf seine Antworten erlaubt. Jede CORS-Konfiguration öffnet also gezielt ein Loch in einem Schutzmechanismus, der standardmäßig alles verweigert. Genau deshalb ist Sorgfalt entscheidend: Ein zu freizügig gesetzter Access-Control-Allow-Origin-Header hebt den Browserschutz für exakt die Angriffe auf, gegen die die Same-Origin Policy ursprünglich gebaut wurde.

2. Simple Requests vs. Preflighted Requests

Nicht jeder Cross-Origin-Request löst vorab eine Prüfung aus. Browser unterscheiden zwischen Simple Requests und Preflighted Requests, und dieser Unterschied bestimmt, wie eine API überhaupt auf Cross-Origin-Zugriffe reagieren muss. Ein Simple Request erfüllt strenge Kriterien: Er nutzt ausschließlich GET, HEAD oder POST, setzt keine benutzerdefinierten Header und beschränkt den Content-Type auf application/x-www-form-urlencoded, multipart/form-data oder text/plain. Solche Requests werden vom Browser direkt an den Server gesendet, die CORS-Prüfung erfolgt erst beim Auswerten der Antwort-Header.

Sobald eine Anfrage von diesem schmalen Rahmen abweicht, etwa durch PUT, DELETE, PATCH, einen Authorization-Header oder Content-Type: application/json, wie es praktisch jede moderne REST- oder GraphQL-API voraussetzt, wird sie zur Preflighted Request. Der Browser schickt dann automatisch zuerst eine OPTIONS-Anfrage, um zu klären, ob der eigentliche Request erlaubt ist, bevor überhaupt Nutzdaten übertragen werden. Für Magento-APIs, die praktisch immer mit JSON arbeiten, ist der Preflight also der Regelfall, nicht die Ausnahme, und muss serverseitig korrekt beantwortet werden.

3. Der Preflight-Request im Detail: OPTIONS, Methods, Headers und Max-Age

Der Preflight-Request ist eine automatische OPTIONS-Anfrage, die der Browser vor dem eigentlichen Request absetzt, ohne dass JavaScript-Code sie explizit auslöst. Er enthält den Header Access-Control-Request-Method mit der geplanten HTTP-Methode und optional Access-Control-Request-Headers mit einer Liste der benutzerdefinierten Header, die der eigentliche Request mitschicken wird. Der Server muss darauf mit den passenden Access-Control-Allow-Methods- und Access-Control-Allow-Headers-Headern antworten, sonst bricht der Browser die eigentliche Anfrage ab, ohne dass beim tatsächlichen Request überhaupt ein Netzwerkfehler sichtbar wird.

Um nicht bei jeder Anfrage einen zusätzlichen Roundtrip zu erzwingen, erlaubt Access-Control-Max-Age dem Server, dem Browser eine Cache-Dauer in Sekunden für das Preflight-Ergebnis mitzuteilen. Ein Wert von 7200 lässt den Browser das Ergebnis zwei Stunden lang wiederverwenden, was bei API-lastigen Single-Page-Applications spürbar Latenz spart. Wichtig: Der Browser deckelt diesen Wert intern, Chromium erlaubt aktuell maximal 7200 Sekunden pro Preflight-Cache-Eintrag, unabhängig davon, welchen höheren Wert der Server sendet.


# Preflight-Request manuell nachstellen, um Server-Antwort zu prüfen
curl -i -X OPTIONS https://api.example.de/rest/V1/graphql \
  -H "Origin: https://shop.example.de" \
  -H "Access-Control-Request-Method: POST" \
  -H "Access-Control-Request-Headers: content-type, authorization"

# Erwartete Antwort bei korrekter Allowlist-Konfiguration
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://shop.example.de
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization, Store
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 7200
Vary: Origin

4. Access-Control-Allow-Origin: Wildcard-Risiken und die Sache mit Credentials

Der Header Access-Control-Allow-Origin: * erlaubt jedem beliebigen Origin, die Antwort zu lesen, und wird oft aus reiner Bequemlichkeit gesetzt, weil er sofort alle CORS-Fehler in der Browser-Konsole zum Verschwinden bringt. Bei einer öffentlichen, unauthentifizierten API ohne sensible Daten ist das tolerierbar. Sobald aber Zugangsdaten im Spiel sind, wird der Wildcard gefährlich: Jede beliebige Webseite könnte im Namen eines eingeloggten Nutzers Anfragen an die API stellen und die Antworten auslesen.

Browser wissen das und blockieren deshalb die Kombination aus Access-Control-Allow-Origin: * und Access-Control-Allow-Credentials: true aktiv: Ein Request mit credentials: 'include' schlägt fehl, sobald der Wildcard gesetzt ist, selbst wenn der Server Credentials eigentlich erlauben wollte. Diese Sicherheitsbremse verhindert versehentliche Kombinationen, verleitet aber viele Entwickler zu einem gefährlichen Workaround.

Der Workaround-Fehler sieht meist so aus: Statt eine feste Origin zu setzen, spiegelt der Server einfach den eingehenden Origin-Header aus dem Request zurück in Access-Control-Allow-Origin. Das umgeht die Browser-Sperre technisch, weil der Wert nun kein Wildcard mehr ist, öffnet aber faktisch dieselbe Lücke wie ein Wildcard mit Credentials, nur unsichtbar in den Server-Logs. Genau dieses Muster wird im nächsten Abschnitt genauer betrachtet.

5. Origin-Reflection ohne Allowlist: der häufigste Fehler

Origin-Reflection bedeutet, dass ein Server bei jeder eingehenden Anfrage den mitgesendeten Origin-Header ungeprüft in Access-Control-Allow-Origin zurückschreibt, statt ihn gegen eine feste Liste erlaubter Domains zu prüfen. Auf den ersten Blick wirkt das wie eine elegante Lösung für Multi-Domain-Setups, weil jede Origin automatisch funktioniert, ohne Konfigurationsaufwand. In der Praxis ist es eine der häufigsten CORS-Schwachstellen überhaupt, weil sie faktisch jede Origin als vertrauenswürdig behandelt.

Kombiniert mit Access-Control-Allow-Credentials: true erlaubt Origin-Reflection einer bösartigen Seite unter evil-domain.de, im Namen eines eingeloggten Nutzers authentifizierte Anfragen an die API zu stellen und die Antwort samt Session-Daten, Bestellhistorie oder persönlichen Informationen auszulesen. Der Browser verhindert das nicht, weil der Server ja aktiv genau diesen Origin erlaubt hat. Automatisierte Scanner suchen gezielt nach diesem Muster, indem sie einen zufälligen Origin-Header senden und prüfen, ob er unverändert reflektiert wird.

Der Unterschied zwischen Reflection und einer echten Allowlist liegt einzig im serverseitigen Vergleich: Der eingehende Origin muss aktiv gegen eine gepflegte Liste erlaubter Werte geprüft werden, bevor er in den Antwort-Header übernommen wird. Diese eine Prüfung trennt eine sichere von einer verwundbaren CORS-Implementierung.

6. Server-seitige Allowlist richtig implementieren

Eine sichere Allowlist besteht aus einer festen, serverseitig gepflegten Liste erlaubter Origins, gegen die jeder eingehende Origin-Header exakt verglichen wird, inklusive Schema und Port. Nur bei einem Treffer wird der Wert unverändert in Access-Control-Allow-Origin gespiegelt, bei jedem anderen Origin bleibt der Header entweder ganz weg oder liefert einen definierten Fallback-Wert ohne Credentials-Freigabe. Wichtig ist zusätzlich der Response-Header Vary: Origin, damit Caches wissen, dass die Antwort vom Origin-Header abhängt, mehr dazu im Abschnitt zu den CDN-Fallstricken.

In Magento lässt sich diese Logik sauber als Plugin auf den Webapi-Response-Sender realisieren, statt CORS-Header hart im Webserver zu verdrahten. Das hat den Vorteil, dass die Allowlist über die Magento-Konfiguration im Admin gepflegt werden kann, statt bei jeder neuen Frontend-Domain einen Deployment-Zyklus für die nginx-Konfiguration auszulösen. Der Plugin-Ansatz greift zudem konsistent für REST- und GraphQL-Endpunkte, weil beide über denselben Webapi-Unterbau laufen.


<?php

declare(strict_types=1);

namespace Mironsoft\Cors\Plugin;

use Magento\Framework\App\Response\Http as HttpResponse;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Store\Model\ScopeInterface;

/**
 * Sets CORS headers on webapi responses based on a server-side origin allowlist.
 */
class CorsHeaderPlugin
{
    /**
     * @param RequestInterface $request Current HTTP request
     * @param ScopeConfigInterface $scopeConfig Store-scoped configuration reader
     */
    public function __construct(
        private readonly RequestInterface $request,
        private readonly ScopeConfigInterface $scopeConfig,
    ) {
    }

    /**
     * Adds Access-Control headers only when the incoming Origin matches the allowlist.
     *
     * @param HttpResponse $subject Webapi response instance
     * @param HttpResponse $result Response after core processing
     * @return HttpResponse
     */
    public function afterSendResponse(HttpResponse $subject, HttpResponse $result): HttpResponse
    {
        $origin = (string) $this->request->getHeader('Origin');
        $allowedOrigins = $this->getAllowedOrigins();

        // Never reflect the Origin header blindly, always compare against a fixed list
        if ($origin !== '' && in_array($origin, $allowedOrigins, true)) {
            $subject->setHeader('Access-Control-Allow-Origin', $origin, true);
            $subject->setHeader('Access-Control-Allow-Credentials', 'true', true);
            $subject->setHeader('Vary', 'Origin', true);
        }

        return $result;
    }

    /**
     * Reads the configured origin allowlist from store configuration.
     *
     * @return string[]
     */
    private function getAllowedOrigins(): array
    {
        $raw = (string) $this->scopeConfig->getValue(
            'mironsoft_cors/general/allowed_origins',
            ScopeInterface::SCOPE_STORE
        );

        return array_filter(array_map('trim', explode(',', $raw)));
    }
}

7. CORS für Magento GraphQL- und REST-APIs im Headless-Setup

Bei einem entkoppelten Frontend im Stil von PWA Studio oder einem selbstgebauten Headless-Setup läuft die Storefront auf einer eigenen Origin, zum Beispiel https://shop.example.de, während die Magento-Instanz mit GraphQL- und REST-Endpunkten unter https://api.example.de erreichbar ist. Aus Sicht des Browsers sind das zwei vollständig unterschiedliche Origins, jede GraphQL-Query und jede REST-Anfrage vom Frontend ist also grundsätzlich ein Cross-Origin-Request und unterliegt CORS.

Für ein produktives Setup gehören mindestens die tatsächlich genutzten Frontend-Domains in die Allowlist: die Produktions-Domain, gegebenenfalls eine Staging-Domain und lokale Entwicklungs-Origins wie http://localhost:3000 nur in der Entwicklungsumgebung, niemals im Produktivsystem. Der GraphQL-Endpunkt benötigt zusätzlich Access-Control-Allow-Headers für Content-Type, Authorization und gegebenenfalls den Magento-spezifischen Store-Header, da GraphQL-Clients diese standardmäßig mitschicken.

Nutzt das Frontend Cookies für Customer-Sessions statt reiner Bearer-Token, muss der Request zusätzlich mit credentials: 'include' gesendet werden, und der Server muss Access-Control-Allow-Credentials: true zusammen mit einer geprüften, nicht reflektierten Origin liefern. Viele Headless-Teams setzen inzwischen bewusst auf zustandslose Token-Authentifizierung, gerade um diese Kombination aus Cookies und CORS-Komplexität zu vermeiden.


<?xml version="1.0"?>
<!-- app/code/Mironsoft/Cors/etc/adminhtml/system.xml -->
<!-- Allowlist als Modul-Konfiguration statt Hardcoding im Webserver -->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
    <system>
        <section id="mironsoft_cors" translate="label" type="text" sortOrder="200"
                 showInDefault="1" showInWebsite="1" showInStore="1">
            <label>CORS Settings</label>
            <tab>mironsoft</tab>
            <resource>Mironsoft_Cors::config</resource>
            <group id="general" translate="label" type="text" sortOrder="10"
                   showInDefault="1" showInWebsite="1" showInStore="1">
                <label>General</label>
                <field id="allowed_origins" translate="label comment" type="textarea"
                       sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
                    <label>Allowed Origins</label>
                    <comment>Comma-separated list of allowed frontend origins, e.g. https://shop.example.de</comment>
                </field>
                <field id="max_age" translate="label" type="text"
                       sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="1">
                    <label>Preflight Max-Age (seconds)</label>
                </field>
            </group>
        </section>
    </system>
</config>

// Headless-Frontend: GraphQL-Query mit Cookie-basierter Customer-Session
async function fetchCustomerCart(query, variables) {
  const response = await fetch('https://api.example.de/graphql', {
    method: 'POST',
    credentials: 'include', // sends and accepts cookies cross-origin
    headers: {
      'Content-Type': 'application/json',
      'Store': 'default',
    },
    body: JSON.stringify({ query, variables }),
  });

  if (!response.ok) {
    // A CORS rejection surfaces here as a network-level failure, not a 4xx status
    throw new Error(`GraphQL request failed: ${response.status}`);
  }

  return response.json();
}

8. Vary: Origin und die Cache-Fallen mit CDN und Varnish

Sobald ein Server Access-Control-Allow-Origin dynamisch abhängig vom eingehenden Origin setzt, wie es eine korrekte Allowlist tut, wird die HTTP-Antwort selbst origin-abhängig. Ein CDN oder ein Varnish Full Page Cache, der davon nichts weiß, cacht die erste Antwort unter einem Cache-Key ohne Origin-Bezug und liefert sie anschließend an alle nachfolgenden Origins aus, egal welchen Origin-Header sie mitschicken. Das Resultat: Origin B bekommt plötzlich den für Origin A bestimmten Access-Control-Allow-Origin-Header und damit im schlimmsten Fall Zugriff auf Daten, die für eine andere Domain gedacht waren.

Der Response-Header Vary: Origin weist konforme Caches an, den Origin-Header als Teil des Cache-Keys zu behandeln und für jeden Origin-Wert eine eigene, separate Cache-Variante vorzuhalten. Ohne diesen Header ist eine dynamische Origin-Allowlist hinter einem CDN faktisch keine sichere Allowlist mehr, weil die falsche Antwortvariante ausgeliefert werden kann. Bei Varnish muss Origin zusätzlich explizit im VCL als Teil des Hash-Keys berücksichtigt werden, da Varnish den Vary-Header nicht in jeder Standardkonfiguration korrekt respektiert.

In der Praxis bedeutet das: Wer CORS-Header hinter Varnish oder einem CDN ausliefert, muss die Cache-Strategie und die CORS-Konfiguration gemeinsam testen, nicht getrennt. Ein einfacher Test mit zwei unterschiedlichen erlaubten Origins und anschließendem Prüfen der jeweils ausgelieferten Antwort-Header deckt Fehlkonfigurationen zuverlässig auf, bevor sie in Produktion zum Datenleck werden.


# nginx: Origin gegen Allowlist prüfen und Vary korrekt setzen
map $http_origin $cors_allowed_origin {
    default "";
    "https://shop.example.de" $http_origin;
    "https://staging.shop.example.de" $http_origin;
}

server {
    location /rest/ {
        # Never use "*" together with credentials, always reflect a checked value
        add_header 'Access-Control-Allow-Origin' $cors_allowed_origin always;
        add_header 'Access-Control-Allow-Credentials' 'true' always;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
        add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, Store' always;
        add_header 'Access-Control-Max-Age' 7200 always;

        # Tells CDN/proxy caches the response depends on the Origin header
        add_header 'Vary' 'Origin' always;

        if ($request_method = 'OPTIONS') {
            return 204;
        }

        proxy_pass http://magento_upstream;
    }
}

9. CORS-Konfigurationen im Vergleich

Die folgende Übersicht fasst die typischen CORS-Fehlkonfigurationen den jeweils sicheren Gegenstücken gegenüber. Die Reihenfolge ist bewusst gewählt: Jede Zeile baut auf der vorherigen auf, eine einzelne unsichere Zeile genügt, um die gesamte Konfiguration zu untergraben.

Konfiguration Unsicher / Riskant Empfohlene Konfiguration Warum
Allow-Origin "*" mit Credentials Geprüfte Origin aus Allowlist Wildcard + Credentials wird vom Browser blockiert oder ist ohne Credentials ein offenes Datenleck
Origin-Prüfung Origin ungeprüft reflektiert Exakter Abgleich gegen feste Liste Reflection behandelt faktisch jede Origin als vertrauenswürdig
Preflight-Caching Kein Access-Control-Max-Age Max-Age sinnvoll gesetzt (z. B. 7200) Reduziert Preflight-Roundtrips ohne Sicherheitsverlust
Cache-Header Kein Vary: Origin hinter CDN/Varnish Vary: Origin gesetzt und im Cache-Key berücksichtigt Verhindert Ausliefern falscher CORS-Header an falschen Origin
Credentials-Handling Allow-Credentials: true bei jedem Origin Credentials nur für geprüfte, vertrauenswürdige Origins Begrenzt die Angriffsfläche auf tatsächlich benötigte Frontends

In der Praxis zeigt sich häufig, dass eine einzelne unsichere Zeile aus dieser Tabelle genügt, um die gesamte CORS-Konfiguration wirkungslos zu machen: Eine korrekte Allowlist bringt wenig, wenn parallel Access-Control-Allow-Credentials bei jedem Origin auf true steht. Wer alle fünf Punkte konsequent umsetzt, schließt die gängigsten CORS-Schwachstellen zuverlässig.

Mironsoft

CORS-Audits, API-Sicherheit und Headless-Absicherung für Magento-Shops

CORS-Konfiguration professionell absichern lassen?

Wir prüfen die CORS-Konfiguration eurer Magento-APIs, schließen riskante Wildcard- und Origin-Reflection-Muster und implementieren eine saubere, server-seitige Allowlist, die auch mit CDN- und Varnish-Caching zuverlässig funktioniert.

CORS-Audit

Analyse bestehender Access-Control-Header, Origin-Allowlists und Preflight-Konfiguration

Headless-Absicherung

Sichere CORS-Konfiguration für PWA- und Headless-Frontends mit Magento GraphQL/REST

Cache-Kompatibilität

Vary: Origin korrekt einsetzen, damit Varnish und CDN keine falschen Header ausliefern

10. Zusammenfassung

CORS richtig zu konfigurieren bedeutet, die Same-Origin Policy des Browsers gezielt und kontrolliert zu öffnen, statt sie versehentlich vollständig auszuhebeln. Der Wildcard Access-Control-Allow-Origin: * ist für öffentliche, unauthentifizierte Endpunkte akzeptabel, wird aber gefährlich, sobald Credentials ins Spiel kommen, und Browser blockieren diese Kombination deshalb aktiv. Origin-Reflection ohne Allowlist umgeht diese Bremse technisch, öffnet aber faktisch dieselbe Lücke und zählt zu den häufigsten CORS-Schwachstellen in der Praxis.

Für Magento-APIs, die von einem entkoppelten PWA- oder Headless-Frontend konsumiert werden, ist eine serverseitige Allowlist mit exaktem Origin-Abgleich, korrekt gesetztem Access-Control-Max-Age für Preflight-Caching und einem sauberen Vary: Origin-Header hinter CDN und Varnish der zuverlässige Weg. Wer diese Bausteine konsequent zusammen testet, statt sie isoliert zu betrachten, vermeidet sowohl blockierte Frontend-Requests als auch stille Sicherheitslücken durch falsch gecachte Antworten.

CORS richtig konfigurieren, das Wichtigste auf einen Blick

Same-Origin & CORS

SOP blockiert standardmäßig alles, CORS öffnet gezielt einzelne Origins über Access-Control-Allow-Origin.

Wildcard & Credentials

Access-Control-Allow-Origin: * mit Credentials wird vom Browser blockiert, Origin-Reflection umgeht das unsicher.

Preflight & Max-Age

OPTIONS-Request prüft Method und Headers vorab, Access-Control-Max-Age cached das Ergebnis bis zu 7200 Sekunden.

Allowlist & Vary

Server-seitige Allowlist plus Vary: Origin verhindert falsche CORS-Header aus CDN- und Varnish-Caches.

11. FAQ: CORS richtig konfigurieren

1Was ist der Unterschied zwischen Same-Origin Policy und CORS?
Die Same-Origin Policy blockiert per Voreinstellung jeden Cross-Origin-Zugriff. CORS ist ein Header-basiertes Verfahren, das diesen Schutz gezielt für bestimmte Origins lockert, statt ihn abzuschalten.
2Warum blockieren Browser Wildcard plus Credentials?
Diese Kombination würde jeder Webseite erlauben, im Namen eines eingeloggten Nutzers Daten auszulesen. Ein Request mit credentials: 'include' schlägt deshalb fehl, sobald der Wildcard gesetzt ist.
3Was ist ein Preflight-Request und wann wird er ausgelöst?
Eine automatische OPTIONS-Anfrage vor einem Cross-Origin-Request, sobald dieser vom Simple-Request-Rahmen abweicht, etwa durch PUT, DELETE, Authorization-Header oder JSON-Content-Type.
4Wofür steht Access-Control-Max-Age?
Gibt an, wie lange der Browser ein Preflight-Ergebnis zwischenspeichern darf. Chromium deckelt den Wert bei 7200 Sekunden, unabhängig vom Server-Wert.
5Simple Requests vs. Preflighted Requests?
Simple Requests nutzen nur GET/HEAD/POST mit eingeschränktem Content-Type. Praktisch jede JSON-basierte REST- oder GraphQL-Anfrage löst dagegen einen Preflight aus.
6Warum ist Origin-Reflection ohne Allowlist gefährlich?
Jeder Origin wird als vertrauenswürdig behandelt. Kombiniert mit Credentials kann eine fremde Seite Daten im Namen eines eingeloggten Nutzers auslesen.
7Wie implementiere ich eine sichere Allowlist in Magento?
Als Plugin auf den Webapi-Response-Sender, das den Origin gegen eine gepflegte Liste vergleicht und nur bei Treffer spiegelt, inklusive Vary: Origin.
8CORS für Magento-GraphQL mit PWA-Frontend?
Nur tatsächlich genutzte Frontend-Domains in die Allowlist, keine Entwicklungs-Origins in Produktion. Content-Type, Authorization und Store-Header in Access-Control-Allow-Headers erlauben.
9Warum ist Vary: Origin bei CDN/Varnish wichtig?
Ohne Vary: Origin cacht ein CDN die erste Antwort und liefert sie an alle Origins aus, was CORS-Header fälschlich an falsche Domains ausliefern kann.
10Reicht es, CORS nur im Frontend zu konfigurieren?
Nein. CORS wird ausschließlich serverseitig über Response-Header gesteuert und vom Browser durchgesetzt, das Frontend kann das nicht beeinflussen.