Is Safari getting stricter with CORS?

A CORS edge case and how we solved it

Andrew den Hertog
Prodigy Engineering
4 min readOct 31, 2023

--

Recently, a member of the team responsible for our marketing website, https://www.prodigygame.com, brought to our attention that in a particular case, on Safari, a couple of files that were being retrieved from our CDN were being blocked by Safari due to its CORS policy.

The CORS error presented to us by Safari

TL;DR

Safari considers the protocol part of the Origin host string against Cross-Origin requests. If you have an issue with CORS errors in Safari, remove any wildcards (*) and add the protocol, which, in most cases, is https:// to the access-control-allow-origin domains.

At first, when the developer alerted us of this issue, it was so difficult to reproduce we knew we had an interesting problem to solve. We initially thought some browser extensions were interfering, but the devs who reported this were not using any extensions. After confirming their browsers were in the same state as mine, we started digging deeper.

After trying several different things, such as enabling and disabling caching and interrupting the loading of the resources, we could reproduce the error.

The reproduction steps were the following:

  1. Close Safari. Right-click the Safari icon on the Dock, select ‘Quit,’ and ensure Safari is no longer running.
  2. Re-open Safari and browse the website.
  3. Refresh the page, and voilà, Safari starts to throw CORS errors!

Since this only occurred on a page refresh when caching is enabled on the browser, Safari does some CORS validation on cached resources after the initial resource is downloaded. Once caching is disabled and flushed, the issue goes away.

Now that we could reproduce the issue, it was time to go to work to fix it.

The first item to look at in debugging this was to validate that our current CORS configuration on our CDN and backing file store was correct. It all appeared okay, using *.prodigygame.com as the allowed origin.

Next, we tried to invalidate and flush our CDN to force the CDN edge nodes to recache every file. A particular edge node may have broken a file. We knew this was unlikely to fix the issue, but we sought to eliminate all possible causes. As we expected, we still needed to fix something.

Since we narrowed this down to being browser-side, specifically Safari, we decided to turn to a Google search to see if the community had any suggestions. Unfortunately, we found very little information except to validate that our current configuration was correct.

We had given up on fixing this, but the developer who alerted us to this issue shared an interesting blog post, which brought me back to the problem. The section on ‘Wildcards in CORS’ says that wildcards should not be used in CORS because some browsers, and here it mentions Safari specifically, don’t support wildcards.

Okay, now we have a lead. We updated our CORS not to have any wildcards and to list each domain and subdomain that needed to be on that list directly to the allow-origin field.

Did this fix things?

No.

We were still getting the same error message.

The error specifically stated: Failed to load resource: Origin https://www.prodigygame.com is not allowed by Access-Control-Allow-Origin. Status code: 200

What stood out to me now was that the protocol https:// was part of the origin of this message.

On a hunch, we decided to add the protocol to the allowed origins URL, so instead of it being just www.prodigygame.com, it was https://www.prodigygame.com.

Fixed!

No more CORS errors.

We’ve never seen the protocol considered in CORS origins before. This felt new to me, but Safari keeps getting tighter with its CORS security.

Doing some follow-up research, we have determined that CORS specification is flexible and that browsers can use a bit of their judgment in implementation. Most err on the side of caution and make it more strict. Ultimately, it was determined that our issue was not because we missed the protocol but that it was a combination of using wildcards without the protocol.

Reading Amazon Web Services documentation on CORS also indicated that the protocol should be part of the AllowedOrigin.

AllowedOrigin element

In the AllowedOrigin element, you specify the origins to allow cross-domain requests from, for example, http://www.example.com. The origin string can contain only one * wildcard character, such as http://*.example.com. You can optionally specify * as the origin to enable all the origins to send cross-origin requests. You can also set https to allow only secure origin.

Ultimately, we have learned that the safe path with CORS is to err on caution. Keep in mind the following when working with CORS:

  • Don’t use wildcards.
  • Ensure you have the protocol as part of the Access-Control-Allow-Origin headers.

For more information on CORS, see this post from Rishabh Poddar that gave us the lead for our fix.

Also, I need to thank Natalie Famula for bringing this to our team’s attention and sharing this lead with us.

Enjoyed this read? Give it a round of applause (or a standing ovation) by clapping 👏! If you want more insightful content, hit that follow button for regular updates.

Don’t forget to subscribe to the Prodigy Engineering distribution, too, for exclusive insights from the world of online education! Your support keeps the words flowing. Happy reading! 📚✨✨

--

--