Content Security Policy in Next.js: Fix Supabase, Analytics and External Images
A CSP that is too strict breaks Supabase, analytics scripts, or external images. A CSP that is too broad loses most of its value.
A Content Security Policy that is too broad doesn't protect much. A CSP that is too strict quickly breaks your site. This is exactly what often happens with Next.js when you plug in Supabase, an analytics tool, external images or some useful scripts.
The goal of a good CSP is not to blindly block everything. The goal is to allow only the necessary origins, nothing more.
Why CSP often breaks a web project
When we add a CSP, we block certain loadings by default:
- external scripts
- inline or external styles
- distant images
- connections to APIs
- iframes or embedded resources
As a result, legitimate bricks stop working:
- Supabase connection
- telemetry or analytics
- Open Graph images or CDN images
- widgets or embedded components
The right reflex is not to remove the CSP. The right reflex is to understand which directive blocks what.
What Next.js recommends
The Next.js documentation points out that a CSP is used to protect against XSS, clickjacking and other injections. She also explains two approaches:
- a CSP configured in
next.config.js - stricter CSP with nonce for cases that need it
For many marketing sites or simple portals, the first approach is sufficient if it is well maintained.
The concrete problem with Supabase
Supabase often needs outbound connections to:
- your project endpoint
- Auth calls
- REST or Realtime calls depending on your use
If your connect-src is too strict, certain operations stop working:
- login
- data reading
- upload or additional calls
The symptom often looks like an application bug, while the browser is already telling you the truth in the console: the CSP is blocking the request.
The concrete problem with external images
Another common breakage concerns images:
- CDN images
- remote Open Graph images
- marketing content served from an external domain
If img-src does not cover these origins, the images will not load.
And if you use next/image, the Next.js configuration must also allow useful image domains. Security therefore occurs at two levels:
- the Next.js image config
- the CSP of the browser
The concrete problem with analytics scripts
Analytics or marketing tools are also classic candidates for scrapping. A well-made CSP should support what you really want to use.
The question is not "how to pass any script". The question is:
- what tool is essential?
- which domain is it loading from?
- should we authorize a script, a connection, a tracking image, or several of these things?
Without this clarification, we often end up sticking wild cards everywhere, and the CSP loses its value.
A clean method to correct
Here is a simple method:
- enable a reasonably strict CSP
- open the browser console
- identify every actual violation
- identify the directive concerned:
script-src,connect-src,img-src,style-src, etc. - add only the necessary origin
- retest
This approach takes a little more time than a blanket copy and paste, but it produces a readable policy.
A basic example
For a classic Next.js project, you can start from a structure like:
Content-Security-Policy:
default-src 'self';
script-src 'self';
style-src 'self' 'unsafe-inline';
img-src 'self' data: https:;
font-src 'self' https: data:;
connect-src 'self' https://your-project.supabase.co;
frame-ancestors 'self';
object-src 'none';
base-uri 'self';
Then you only open what is justified:
- a well-identified analytics domain
- a clearly identified image CDN
- an additional domain required by your stack
The important point is to keep the list short and understandable.
What not to do
Avoid these three mistakes:
- add
*everywhere to "fix the problem" - stack domains without knowing why they are there
- forget to retest after adding a new tool
An unmaintained CSP quickly ends up in technical debt. It gives a false sense of security and becomes difficult to understand.
The right framework for a clean Next.js site
For a clean project in production, keep this logic:
frame-ancestorsto limit boardingobject-src 'none'base-uri 'self'connect-srclimited to real APIsimg-srcexplicitscript-srcandstyle-srcopen only if necessary
If your project grows or relies heavily on dynamic scripting, then move to a stricter policy with nonce. But don't make everything too complicated too soon if the need does not yet require it.
How to know if your CSP is healthy
Ask yourself these questions:
- Does each licensed domain have a clear reason for existing?
- Do useful Supabase feeds work?
- Do the essential images and analytics tools work?
- Have you avoided unnecessary wild cards?
- Can anyone on the team read the policy again and understand it?
If the answer is yes, you already have a much better foundation than most sites.
What to remember
A good CSP in Next.js is neither a blind list of blocks nor an open highway to everything. It's a clear inventory of what your site actually loads.
For Supabase, analytics and external images, the right strategy is always the same: identify the real dependencies, open just enough, then retest. This is what provides useful security, without breaking the product.
Official sources
Keep reading on the same topic
These links reinforce the blog's topical cluster and help search engines understand the article's primary subject.
