Getting strange Access-Control-Allowed-Origin headers

Hi, we deployed a SvelteKit site to Netlify and with one of the latest releases of SvelteKit, the CORS is also checked when doing SSR (see simulate CORS errors in server-side fetch by Rich-Harris · Pull Request #6550 · sveltejs/kit · GitHub)

Since the site started to generate these CORS errors, I did some debugging and noticed that the Dato CMS GraphQL API returns http://localhost:5173 as Access-Control-Allowed-Origin on a totally different domain. This is the URL I was previously using for local developing.

The issue doesn’t arise when the Browser performs the requests, it’s strictly happening in a Server-to-Server context. So I was wondering why this is? Could it be, that DatoCMS caches an origin for a given API Key? Could it be that the Origin header is missing in the request and DatoCMS is using a cached value for the response?

Why is DatoCMS not responding with Access-Control-Allowed-Origin: * ?

Quick update: I can confirm that the request does not have an Origin header value set when doing Server-to-Server communication. So the question/problem boils down to:

If the graphql request does not have an Origin set, the response from DatoCMS might contain an invalid Access-Control-Allowed-Origin value. Ideally, the value would be * in these cases…

Update: This is a bug in SvelteKit (Add `Origin` request header for the server-side fetch · Issue #6608 · sveltejs/kit · GitHub), since the Origin header should be set for these requests. Maybe it’s still worth investigating by your engineers what should happen if the Origin is missing?

Hello @tools1 and welcome to the community,

I’ll check with the development team on how we deal with empty Origin headers and i’ll get back to you.

Thank you for letting us know!

Request without Origin:

curl 'https://graphql.datocms.com/' -X POST -H 'Accept: application/json' -H 'Content-Type: application/json' -H 'Authorization: Bearer XXX' --data-raw '{"query":"{ blogPost{ title } }"}' -v

Response:

< HTTP/2 200
< date: Fri, 16 Sep 2022 15:38:31 GMT
< content-type: application/json; charset=utf-8
< access-control-allow-origin: *
< access-control-allow-credentials: true
< access-control-allow-headers: authorization, content-type, x-environment, x-site-domain, x-api-version, user-agent, x-session-id, x-include-drafts, x-exclude-invalid
< access-control-allow-methods: GET, POST, PUT, OPTIONS, DELETE
< access-control-expose-headers: x-ratelimit-limit, x-ratelimit-remaining, x-ratelimit-reset
< access-control-max-age: 1728000
< vary: Authorization, Accept-Encoding, X-Environment, X-Include-Drafts, X-Exclude-Invalid, Origin

So with no Origin, we respond with *.

The header access-control-allow-origin: http://localhost:5173 can only be returned when the request contains an origin: http://localhost:5173 header :confused:

Also note that the vary header contains origin, so requests with different origins are treated differently, and do not use the same cache.

Thanks for your replies. I’m still not sure how the localhost origin appeared on the deployed website… could it be related to caching?

Either way, the issue in SvelteKit is now fixed and should send a proper Origin header with each request.