← Alle checks
BeveiligingTypische ernst: Hoog

Scanner voor te ruime CORS

Controleert of je CORS-beleid elke origin met inloggegevens weerspiegelt en zo de data van je gebruikers blootstelt.

Wat het checkt

Deze scanner controleert je CORS-beleid om te zien of het verzoeken vanaf elke origin accepteert en tegelijk toestaat dat credentials worden meegestuurd. Die combinatie is de gevaarlijkste CORS-opzet die er is. Hij kijkt alleen naar hoe je op cross-domain verzoeken reageert, zonder gegevens te raadplegen.

Waarom het belangrijk is

Als je elke origin met credentials terugkaatst, kan een kwaadaardige site verzoeken naar je API sturen met de sessie van een ingelogde gebruiker en de respons lezen. Dat stelt de privégegevens van je gebruikers bloot aan derden. Meestal gebeurt het door een open configuratie uit voorbeelden of tutorials te kopiëren.

Hoe je het oplost

Vervang de wildcard-origin door een expliciete lijst van vertrouwde domeinen die je API echt nodig hebben. Hoef je geen credentials tussen domeinen te sturen, zet die optie dan uit. Bekijk de CORS-configuratie van je backend of framework en vermijd het automatisch terugkaatsen van de binnenkomende origin.

Hoe deze controle werkt

Scanaris vraagt je homepage opnieuw op met een Origin-header van een verzonnen domein, zoals de browser zou doen als een andere website je probeerde aan te roepen, en kijkt wat je server antwoordt. Geeft Access-Control-Allow-Origin diezelfde origin terug en staat bovendien Access-Control-Allow-Credentials op true, dan opent het een bevinding met hoge ernst: je server spiegelt elke origin met credentials. Antwoordt hij met de wildcard * samen met credentials, dan opent het er een met lage ernst: browsers weigeren die combinatie, maar hij verraadt een blind gemaakte configuratie. Alleen de gescande URL wordt getest; leeft je API op een ander pad of domein, test die dan met het commando hieronder.

Wat een aanvaller hiermee doet

Hij zet op een willekeurig domein een pagina op met een fetch naar je API met credentials: 'include'. Wanneer een van je gebruikers, met een open sessie, die pagina bezoekt, voegt de browser zijn cookies toe, antwoordt je server met de data van de gebruiker en, omdat het CORS-beleid het toelaat, leest de pagina van de aanvaller ze uit. Profiel, bestellingen, berichten, alles wat de API teruggeeft. De gebruiker ziet niets: het gebeurt op de achtergrond.

Waarom het gebeurt

CORS bestaat zodat de browser standaard cross-domain-leesbewerkingen blokkeert. Als een aanroep faalt tijdens de ontwikkeling (de app op de ene poort, de API op de andere), is de snelle oplossing uit tutorials en AI-tools "alle origins toestaan", en om cookies te laten werken komt er "met credentials" bij. In productie betekent dat dat de bescherming is uitgezet. Meer details in verkeerd geconfigureerde CORS: de stille fout die je gebruikers blootstelt.

Hoe je het oplost

  • Expliciete lijst van origins. Alleen de domeinen die je API echt vanuit de browser aanroepen. In Express: cors({ origin: ['https://app.jouwdomein.com'], credentials: true }). In Next.js vergelijk je in de Route Handler de Origin met je lijst voordat je hem teruggeeft. In Nuxt met routeRules en de optie cors of een servermiddleware.
  • Spiegel nooit de origin. De waarde van Origin in het antwoord kopiëren "omdat dan alles werkt" is precies de fout die de controle meet.
  • Heb je geen cookies tussen domeinen nodig, verwijder dan Access-Control-Allow-Credentials. Zonder credentials is een * op een publieke alleen-lezen-API aanvaardbaar.
  • Voeg Vary: Origin toe wanneer het antwoord van de origin afhangt, zodat geen enkele cache aan het ene domein het antwoord van het andere serveert.
  • Cookies met SameSite=Lax of Strict als tweede barrière: zelfs als CORS faalt, stuurt de browser ze niet vanaf een andere site.

Controleer of het is opgelost

curl -sI -H "Origin: https://evil.example" https://jouwdomein.com/api/me | grep -i "access-control"

De juiste uitkomst is dat Access-Control-Allow-Origin voor die origin niet verschijnt, of verschijnt met jouw domein en niet met evil.example. Test ook met je eigen domein in Origin om te bevestigen dat je app nog werkt.

Veelgestelde vragen

Mijn API is publiek en zonder login. Is dat een probleem?

Nee, als er geen cookies of autorisatieheaders zijn. Access-Control-Allow-Origin: * zonder credentials is de juiste configuratie voor een open API.

Ik heb meerdere subdomeinen die de API aanroepen.

Som ze allemaal op of valideer de Origin tegen een strikt patroon van je rootdomein. Valideer nooit met "bevat jouwdomein.com": jouwdomein.com.evil.example voldoet daaraan.

En localhost om te ontwikkelen?

Voeg het alleen toe in de ontwikkelomgeving, via een omgevingsvariabele. Een http://localhost:3000 in de productielijst is een origin die elk programma op de computer van de gebruiker kan gebruiken.

Check het op je site

Scan je site gratis en zie of deze en 44 andere checks slagen, met een fixprompt voor elk probleem.

Mijn site gratis scannen

Uit de blog

Gerelateerde checks