Extras · Checked on every page
CORS configurationWhat it checks and how to fix it
What it checks
Requests the page with an Origin header from an unrelated site (https://example.com) and reads the Access-Control-* headers that come back. No CORS headers passes, as it should for an ordinary website. It fails when Access-Control-Allow-Origin is * together with Access-Control-Allow-Credentials: true, and warns when the server echoes back whatever origin it is sent.
Why it matters
CORS decides which other websites may read your responses from a visitor's browser. A server that reflects any Origin, especially with credentials allowed, lets a malicious page make requests as your logged-in users and read the answers: their personal data, API keys or CSRF tokens. The wildcard plus credentials combination is rejected by browsers anyway, which usually means the configuration was written by trial and error and deserves a second look.
How to fix it
Only send CORS headers on endpoints that really are called from another origin, and answer with an allowlist instead of echoing the request's Origin.
nginx
map $http_origin $cors_origin {
default "";
"https://app.example.com" $http_origin;
"https://admin.example.com" $http_origin;
}
location /api/ {
add_header Access-Control-Allow-Origin $cors_origin always;
add_header Access-Control-Allow-Credentials true always;
add_header Vary Origin always;
}
Rails with the rack-cors gem:
# config/initializers/cors.rb
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins "https://app.example.com", "https://admin.example.com"
resource "/api/*", headers: :any, methods: [:get, :post, :patch, :delete], credentials: true
end
end
Cloudflare: CORS headers come from your origin; if you add them with a Transform Rule, use a fixed origin value rather than copying the request header.
For a truly public, read-only API, Access-Control-Allow-Origin: * is fine as long as you never also send Access-Control-Allow-Credentials: true.