The Absolute Bare Minimum CSP Policy (and why it's not enough)
The simplest, most restrictive Content Security Policy you can implement is Content-Security-Policy: default-src 'self';. This tells the browser to only load resources (scripts, styles, images, fonts, frames, etc.) from your own domain. While technically a valid policy, it will almost certainly break a modern website relying on any external services.
For a functional, secure website in 2024, a truly effective “minimum” policy is more nuanced. It balances strictness with the reality of third-party integrations, offering genuine protection without crippling your site.
Why Bother With CSP Headers Anyway?
Web security isn't just for big corporations; it's a critical concern for every SME, freelancer, and startup founder. One of the nastiest threats is Cross-Site Scripting (XSS). An XSS attack occurs when a malicious actor injects client-side scripts into web pages viewed by other users. These scripts can steal session cookies, deface websites, redirect users to phishing sites, or even trigger malware downloads.
CSP acts as your browser's bouncer, defining exactly what content sources are allowed to load and execute on your site. If a script from an unauthorized domain tries to run, or if an inline script (that hasn't been explicitly allowed) appears, CSP blocks it. This significantly reduces the attack surface for XSS and other content injection vulnerabilities, making your site a much harder target for bad actors.
In 2023, the average cost of a data breach for SMEs ranged from hundreds of thousands to millions of dollars, not counting reputational damage. CSP is a low-cost, high-impact defense.
What Does a “Realistic Minimum” CSP Look Like for a Modern Site?
As established, default-src 'self' is a good starting point, but it's rarely sufficient. Modern sites pull resources from various legitimate sources. Here's a breakdown of common directives and what a pragmatic policy often includes:
default-src 'self': Your baseline. Allows resources from your own domain.script-src: Controls JavaScript sources. This is where most of the work happens. You'll likely need to list CDNs, analytics providers, and payment gateways.style-src: For CSS stylesheets. Often includes font providers.img-src: For images. May include CDNs, analytics tracking pixels, or data URIs.font-src: For web fonts (e.g., Google Fonts).connect-src: Specifies which URLs XHR, WebSockets, and EventSource can connect to. Essential for analytics, error monitoring, and APIs.frame-src: Defines valid sources for<frame>,<iframe>,<object>,<embed>, and<applet>elements. Crucial for payment forms or embedded content.form-action: Specifies valid endpoints for HTML<form>submissions.
Let's consider a practical example for a typical startup website using common tools:
Content-Security-Policy: default-src 'self';
script-src 'self' https://www.googletagmanager.com https://www.google-analytics.com https://js.stripe.com https://browser.sentry-cdn.com https://app.posthog.com;
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
img-src 'self' data: https://www.google-analytics.com https://res.cloudinary.com;
font-src 'self' https://fonts.gstatic.com;
connect-src 'self' https://www.google-analytics.com https://sentry.io https://app.posthog.com;
frame-src 'self' https://js.stripe.com;
object-src 'none';
base-uri 'self';
form-action 'self';
report-uri /csp-report-endpoint;In this policy:
- We allow scripts from Google Tag Manager, Google Analytics, Stripe (for payment forms), Sentry (for error monitoring), and PostHog (for product analytics).
- Styles are allowed from Google Fonts and also include
'unsafe-inline'. We'll address why this is often a compromise below. - Images can come from your site, be data URIs (small embedded images), or be served from Cloudinary (a common image CDN).
- Fonts are loaded from Google Fonts.
- Connections for analytics and error reporting are permitted.
- Stripe's iframe for secure payment forms is allowed.
object-src 'none'blocks Flash and other plugins entirely (a good default).base-uri 'self'prevents injection of malicious base URLs.form-action 'self'ensures all forms submit to your own domain.report-uri /csp-report-endpoint(orreport-to) is crucial for monitoring.
The 'Unsafe' Directives: When to Compromise (and How to Avoid It)
You might have noticed 'unsafe-inline' in the style-src directive above. This is a common, though regrettable, necessity for many applications. It allows inline <style> tags and attributes like style="...". While convenient, it reintroduces an XSS vector, as an attacker could inject malicious inline styles or scripts.
The ideal solution is to avoid inline styles and scripts entirely, moving them to external files. For dynamically generated inline styles, a better approach involves using CSP hashes or nonces. However, implementing these can be complex, especially with legacy code or certain frameworks. For quick wins, 'unsafe-inline' for style-src is often a pragmatic interim step.
'unsafe-eval' is another directive that permits the use of eval() and similar methods. Some older JavaScript libraries or certain framework builds might require it. Like 'unsafe-inline', it should be used with extreme caution and only if absolutely necessary, as it significantly weakens your CSP.
CSP-Report-Only: Your Safety Net During Implementation
Deploying a strict CSP without proper testing can easily break your website, leading to frustrated users and lost business. This is where Content-Security-Policy-Report-Only comes in handy.
Instead of blocking unauthorized content, this header instructs the browser to merely report violations to a specified URI (using the report-uri or report-to directive). Your site continues to function normally, but you gain invaluable insights into what your policy would block.
At SISL, we often start clients with a Report-Only header. This allows us to collect real-world violation reports from live user traffic without impacting their site's functionality. We can then refine the policy iteratively, adding necessary domains and directives, until it's ready for full enforcement. Tools like Sentry, PostHog, or even custom endpoints can aggregate these reports, turning potential chaos into actionable data.
Beyond the Basics: Hardening Your Site Further
CSP is a powerful layer, but it's part of a broader security strategy. Once you've got a solid CSP in place, consider these additional headers for even stronger defense:
- HTTP Strict Transport Security (HSTS): The
Strict-Transport-Securityheader forces browsers to interact with your site only over HTTPS, preventing downgrade attacks and cookie hijacking. - Subresource Integrity (SRI): For critical scripts and stylesheets loaded from third-party CDNs, SRI ensures that the files haven't been tampered with. It uses a cryptographic hash to verify the integrity of the resource.
- Referrer-Policy: Controls how much referrer information is sent with requests, helping protect user privacy.
- Permissions-Policy (formerly Feature-Policy): Allows you to selectively enable or disable browser features and APIs (like camera, microphone, geolocation) for your website and any embedded iframes.
These layers, when combined with a robust CSP, create a formidable defense against a wide range of web vulnerabilities. They demonstrate a commitment to security that builds trust with your users and protects your business.
Conclusion: Pragmatic Security is Achievable
Implementing Content Security Policy headers might seem daunting, especially when dealing with a multitude of third-party services. However, by starting with a pragmatic, realistic minimum and incrementally refining it using Report-Only mode, you can significantly enhance your website's security posture without disrupting your operations.
It's not about achieving a theoretically perfect, impenetrable fortress overnight, but about building robust, actionable defenses that mitigate the most common and damaging threats. For deeper dives into web security architecture, or if you're feeling overwhelmed by the specifics of your tech stack, don't hesitate to get in touch. As a boutique studio, SISL often helps businesses navigate these complexities, ensuring their online presence is both functional and secure.