CORS for CDN and Static Assets
Configure CORS headers for serving fonts, images, and scripts from a CDN. Covers S3, CloudFront, Cloudflare, and common issues with font loading.
Detailed Explanation
Why CDN Assets Need CORS
When a web page at https://app.example.com loads a font from https://cdn.example.com, the browser treats this as a cross-origin request. Without CORS headers, the font will be blocked (particularly by Firefox), causing FOUT (Flash of Unstyled Text) or missing glyphs.
Resources That Require CORS
| Resource | CORS Required? |
|---|---|
Fonts (@font-face) |
Yes — always cross-origin blocked |
Images in <canvas> |
Yes — drawImage taints the canvas |
| JavaScript modules | Yes — <script type="module"> uses CORS |
Regular <script> |
No — loaded in "no-cors" mode |
Regular <img> |
No — unless read via canvas |
| CSS stylesheets | No — unless using fetch() |
AWS S3 + CloudFront
S3 bucket CORS configuration:
[
{
"AllowedHeaders": ["*"],
"AllowedMethods": ["GET", "HEAD"],
"AllowedOrigins": ["*"],
"ExposeHeaders": ["Content-Length", "Content-Type", "ETag"],
"MaxAgeSeconds": 86400
}
]
CloudFront: Add Origin to the Origin Request Policy and Access-Control-Allow-Origin to the Response Headers Policy.
Cloudflare
Cloudflare Workers can add CORS headers:
addEventListener("fetch", (event) => {
event.respondWith(handleRequest(event.request));
});
async function handleRequest(request) {
const response = await fetch(request);
const newHeaders = new Headers(response.headers);
newHeaders.set("Access-Control-Allow-Origin", "*");
newHeaders.set("Access-Control-Max-Age", "86400");
return new Response(response.body, { ...response, headers: newHeaders });
}
Nginx for Static Files
location ~* \.(woff2?|ttf|eot|otf|svg|png|jpg|webp)$ {
add_header Access-Control-Allow-Origin "*" always;
add_header Access-Control-Max-Age 86400 always;
add_header Cache-Control "public, max-age=31536000, immutable";
}
Font-Specific Tip
If fonts load in Chrome but not Firefox, it is almost certainly a CORS issue. Firefox is stricter about enforcing CORS for @font-face resources.
Use Case
A web application loads custom web fonts from a CDN subdomain. Fonts render correctly in Chrome but are missing in Firefox. The fix is adding Access-Control-Allow-Origin: * to the CDN's response headers for font files.