CORS and Security Attributes
Background
When loading scripts from external domains, browsers enforce Cross-Origin Resource Sharing (CORS) policies. CORS controls how resources on one domain can be requested by scripts running on another domain. For third-party scripts, this affects:
- Whether the browser sends cookies with requests
- Access to error details for debugging
- Subresource Integrity (SRI) validation
Default Behavior
Nuxt Scripts applies privacy-focused defaults to all scripts:
<script
src="https://example.com/script.js"
crossorigin="anonymous"
referrerpolicy="no-referrer"
></script>
These defaults:
crossorigin="anonymous"- Prevents the script from sending cookies to third-party serversreferrerpolicy="no-referrer"- Prevents sharing the page URL with third-party servers
This improves user privacy but may break scripts that require cookies or referrer information.
Common CORS Errors
Script Fails to Load
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource
This occurs when a server doesn't return proper CORS headers but crossorigin="anonymous" is set. Some third-party scripts don't support CORS.
Script Loads but Functions Fail
The script loads but functionality is broken because it expected cookies or session data.
Error Details Hidden
window.onerror = msg => console.log(msg)
// Shows: "Script error." instead of actual error
Without crossorigin, browsers hide error details from external scripts for security.
Configuring CORS Attributes
Per-Script Configuration
Disable CORS attributes for scripts that don't support them:
useScript({
src: 'https://example.com/script.js',
crossorigin: false, // Remove crossorigin attribute
referrerpolicy: false, // Remove referrerpolicy attribute
})
Or use a different crossorigin value:
useScript({
src: 'https://example.com/script.js',
crossorigin: 'use-credentials', // Send cookies with request
})
Global Configuration
Change defaults for all scripts:
export default defineNuxtConfig({
scripts: {
defaultScriptOptions: {
crossorigin: false,
referrerpolicy: false,
}
}
})
Crossorigin Values
| Value | Cookies Sent | Error Details | Use Case |
|---|---|---|---|
anonymous | No | Yes (if server supports) | Privacy-focused default |
use-credentials | Yes | Yes | Scripts requiring auth |
false | Yes | No | Scripts without CORS support |
Registry Scripts
Many registry scripts already disable CORS attributes because the third-party doesn't support them:
const config = {
scriptInput: {
src: 'https://js.stripe.com/basil/stripe.js',
crossorigin: false,
referrerpolicy: false,
}
}
Scripts with crossorigin: false include:
- Stripe
- YouTube Player
- Google Sign-In
- Google reCAPTCHA
- Meta Pixel
- TikTok Pixel
- X (Twitter) Pixel
- Snapchat Pixel
- Cloudflare Web Analytics
- Lemon Squeezy
- Matomo Analytics
If a registry script fails, check if CORS configuration needs adjustment.
Subresource Integrity
When using bundled scripts with SRI, you must include crossorigin="anonymous", which Nuxt adds automatically:
export default defineNuxtConfig({
scripts: {
assets: {
integrity: true, // Automatically sets crossorigin="anonymous"
}
}
})
Troubleshooting
Script Won't Load
- Check browser console for CORS errors
- Set
crossorigin: falseto disable CORS mode - Verify the third-party server supports CORS headers
Script Loads but Broken
- The script may require cookies - try
crossorigin: 'use-credentials' - The script may need the referrer - set
referrerpolicy: false - Check if the script expects you to load it without CORS attributes
Debugging External Script Errors
To see full error messages from external scripts:
- Ensure the script has
crossorigin="anonymous" - Verify the server returns
Access-Control-Allow-Originheader - If the server doesn't support CORS, you won't get detailed errors
Bundling as Alternative
If CORS issues persist, consider bundling the script to serve it from your own domain, eliminating CORS entirely.