Security Glossary

Content Security Policy (CSP)

Content Security Policy is an HTTP response header that instructs browsers to only load resources (scripts, styles, images, fonts) from explicitly approved sources, providing a strong defense against XSS and data injection attacks.

Understanding Content Security Policy (CSP)

CSP works by declaring a whitelist of trusted content sources for each resource type. When a browser encounters a resource that violates the policy — such as an inline script when unsafe-inline is not permitted, or a script loaded from an unapproved domain — it blocks the resource and reports the violation. This means even if an attacker successfully injects a script tag via XSS, the browser refuses to execute it.

A CSP is defined through directives like script-src (JavaScript sources), style-src (CSS sources), img-src (images), connect-src (AJAX/WebSocket endpoints), and default-src (fallback for unspecified types). The most impactful directive for security is script-src. Setting script-src 'self' ensures only scripts from your own domain execute, blocking injected external scripts entirely.

The challenge with CSP is that many applications rely on inline scripts and styles, which CSP blocks by default. Solutions include nonce-based CSP (adding a random nonce attribute to each script tag and whitelisting that nonce in the policy), hash-based CSP (whitelisting the SHA hash of specific inline scripts), and strict-dynamic (automatically trusting scripts loaded by already-trusted scripts). These approaches are more secure than adding unsafe-inline, which largely defeats CSP's XSS protection.

CSP also offers a report-only mode (Content-Security-Policy-Report-Only) that logs violations without blocking them, allowing you to test a policy before enforcement. Reports can be sent to a URI defined in the report-uri or report-to directive.

Why This Matters for Vibe-Coded Apps

AI-generated applications almost never include a Content Security Policy because CSP requires careful tuning to avoid breaking legitimate functionality. Vibe-coded apps that use third-party analytics, chat widgets, or payment forms need those domains whitelisted in the CSP, which requires understanding every external resource your app loads.

The most practical approach for vibe-coded apps is to start with CSP in report-only mode, monitor what gets flagged, and iteratively build your policy. Tools like Vibe App Scanner detect missing CSP headers and can identify which directives you need based on the resources your application loads.

Real-World Examples

GitHub CSP Implementation

GitHub implemented one of the most restrictive CSPs of any major web application, using nonce-based script whitelisting and strict-dynamic. This policy prevented XSS exploitation even when injection points were found, as the browser refused to execute attacker-injected scripts.

Google Maps API CSP Bypass (2019)

Researchers demonstrated that certain Google-hosted APIs could be used to bypass CSP policies that whitelisted Google domains. By loading the Google Maps API (which evaluates callbacks), attackers could execute arbitrary JavaScript despite a seemingly strict CSP.

Twitter CSP Evolution

Twitter progressively tightened their CSP over several years, starting with a permissive policy and gradually removing unsafe-inline, switching to nonce-based script loading, and adding strict-dynamic. This incremental approach is a model for deploying CSP on complex applications.

Frequently Asked Questions

Will CSP break my website?

It can if configured incorrectly. CSP blocks any resources that are not explicitly whitelisted. If your app uses inline scripts, third-party widgets, or CDN-hosted libraries, these must be accounted for in the policy. Start with Content-Security-Policy-Report-Only to see what would be blocked without actually breaking anything. Then adjust the policy until there are no violations before switching to enforcement mode.

What is the difference between CSP nonce and hash?

A nonce is a randomly generated value that changes with every page load. You add it as an attribute to script tags and include it in the CSP header. A hash is the SHA-256/384/512 digest of the exact script content, included in the CSP. Nonces are better for dynamic scripts because you only need to update the attribute. Hashes are better for static inline scripts that never change. Both are far more secure than unsafe-inline.

Does CSP replace the need for output encoding?

No. CSP is a defense-in-depth layer, not a replacement for proper output encoding. Output encoding prevents XSS at the source by ensuring user input is rendered as text, not executable code. CSP acts as a safety net — if encoding is missed somewhere, CSP can still block the injected script. Best practice is to implement both: encode all output AND deploy a strict CSP.

What is strict-dynamic in CSP?

strict-dynamic tells the browser that any script loaded by an already-trusted script should also be trusted, regardless of its source. This is useful for applications that dynamically load scripts (code splitting, lazy loading) because you only need to trust the initial script loader via a nonce, and everything it loads is automatically permitted. It simplifies CSP for modern applications that use module bundlers.

Is Your App Protected?

VAS automatically scans for vulnerabilities related to content security policy (csp) and provides detailed remediation guidance. Our scanner targets issues common in AI-generated applications.

Scans from $5, results in minutes. Get actionable fixes tailored to your stack.

Get Starter Scan