You're right, the real issue is CloudFront won't include Origin in the Vary response header if it wasn't included in the initial request. And if you change your HTML attributes, you're changing your request, but you essentially end up with a poisoned local cache. Rolling out crossorigin="anonymous" on previously cached assets is a subtlety you won't know about (even if you think you know CORS) until your site breaks as critical assets are missing.
Yeah, it's generally understood that you need to change the URL to cache-bust when the content changes, but it's easy to forget that you need to do the same thing if important headers change.
Hmm, I think I'll add a section to the article on this when I'm back at my laptop.
If your data is coming from an S3 origin and the original (cached request) was not CORS (but you also want to support CORS), then you can inject the necessary headers with Lambda@Edge or CloudFront Functions.
S3 is used as an example, as it does not include a Vary header for non-CORS requests. However, the same would be true of some other origin which isn't correctly inserting a Vary header.
That works, but I found a simpler / cheaper alternative to fix this particular Cloudfront problem: Create a custom "Cache policy" that only includes the header "origin" and then the answer from Cloudfront will always include "Vary: origin", even if it wasn't in the request (That behaviour is not documented anywhere I could find, stumbled upon it by accident)
Ha, I feel your pain, I ran into something similar with Chrome and Cloudfront.
For us it got triggered because an image on the site appeared both as a video "poster" attribute (which loads with CORS) and as a regular image. So depending on which image the user encountered first you would see a CORS error. But it would be gone after a reload, so devilishly hard to reproduce until you realise what's happening.
Also took me ages to figure out that Cloudfront didn't include the Origin in the Vary header if it wasn't in the original request.
(@jaffathecake perhaps that Cloudfront behaviour warrants a special mention. Great article by the way, I learned a lot)
Getting Vary right isn't just important for Chrome, it's important for CDNs too.