How to Build a Content Security Policy
Learn what Content Security Policy does, how its main directives work and how to build a policy that matches the resources your website actually needs.
Content Security Policy, usually shortened to CSP, is a browser security mechanism that lets a website describe which sources are allowed for different types of content. Instead of allowing a page to load scripts, styles, images and other resources from anywhere, a CSP can restrict those resources to known origins and schemes. The policy is delivered most commonly through an HTTP response header.
Why Content Security Policy matters
A modern website can depend on JavaScript, CSS, fonts, images, APIs, frames and third-party services. If the browser accepts all of those resources without restrictions, an injected script or unexpected reference can have more room to execute. CSP adds another browser-enforced layer by declaring what the page is allowed to load.
CSP is not a substitute for fixing an injection vulnerability. It is a defense-in-depth control that can reduce the impact of some classes of unwanted content when the policy is designed and tested correctly.
The most important CSP directives
default-src
default-src provides a fallback source list for resource types that do not have their own more specific directive. A common starting point is 'self', meaning resources should normally come from the site's own origin unless another directive allows something else.
script-src
script-src controls JavaScript sources. Keep this list as narrow as practical. Broad allowances such as 'unsafe-inline' can weaken the policy, so they should only be used when an application genuinely requires them.
style-src
style-src controls stylesheet sources. Some sites also need inline styles, but allowing them should be a deliberate compatibility decision rather than an automatic default.
img-src and font-src
Images and fonts often come from a small set of known origins. img-src can allow local images, HTTPS resources or data URLs where needed. font-src can similarly name the origins used for web fonts.
connect-src
connect-src applies to browser connections made by APIs and related features. If a site calls a separate API origin, that origin may need to be included.
frame-src and frame-ancestors
frame-src controls the sources a page may load inside frames. frame-ancestors controls which other pages may embed the protected page. These directives solve different problems and should not be treated as interchangeable.
Start with the resources your site actually uses
A CSP is easier to maintain when it reflects the real architecture of the site. List the scripts, styles, fonts, images, APIs and embedded services your pages need. Then create source lists for those dependencies instead of starting with broad wildcards.
For example, a simple static page might only need its own origin for scripts and styles, HTTPS images, and a small set of API origins. A larger application may require additional sources for analytics, payments or embedded content. The correct policy therefore depends on the site.
Header or meta tag?
The HTTP Content-Security-Policy response header is normally the preferred way to deploy CSP because the browser receives the policy with the document response. A meta tag can be useful for some static hosting situations, but it does not provide every CSP capability and must be placed in the document head.
Test before enforcing a restrictive policy
An incorrectly configured CSP can block legitimate resources. After creating a policy, load the real pages and watch the browser console for blocked scripts, styles, fonts, images or connections. A report-only deployment can also be useful when the hosting environment supports it, because it lets a team observe violations before enforcement.
Common CSP mistakes
- Using
*everywhere simply to stop console errors. - Adding
'unsafe-inline'or'unsafe-eval'without checking whether they are actually required. - Forgetting a separate API origin in
connect-src. - Assuming
frame-srcandframe-ancestorscontrol the same direction of framing. - Deploying a restrictive policy without testing all important pages and features.
- Treating CSP as a replacement for secure application code and other response-header controls.
Use a generator as a starting point
A generator can make the initial policy easier to assemble, but the output still needs to be reviewed against the actual website. NeroTool's CSP Generator builds the header value and a meta-tag representation locally, so you can experiment with common directives without uploading a configuration.