Glossary
Content Security Policy
CSP restricts which resources a browser may load and run on a page. It is a defensive layer against XSS, not a substitute for safe output and validation.
Short definition
Rules for the browser, not a fix for server-side bugs.
Content Security Policy (CSP) is a set of instructions that a server sends to a browser, most often in the Content-Security-Policy header. The browser uses them to decide whether a document may load or run a particular script, style, image, font, iframe, or API connection. The policy narrows the space in which injected content can cause harm.
CSP is most commonly used as defence in depth against cross-site scripting. Correct output escaping, safe HTML handling, and input checks remain essential: CSP can limit the consequences of a vulnerability, but does not remove it or sanitise data. It can also restrict other sites from embedding the page or prevent unwanted browser connections.
Use cases
Where the policy defines practical boundaries
CSP is valuable when an application knows its own resources and can continually verify their allowlist.
- a PHP application with its own JavaScript, CSS, and images on the same domain
- an administration interface where a compromised inline script could read user data
- an online store with payment, analytics, or chat integrations from specific domains
- a frontend whose connect-src allows calls only to known APIs
- gradually tightening an older application through report-only mode
Practical example
Gradually tightening an administration interface
The administration interface first sends a report-only policy, and the team observes which first-party assets, CDNs, and integration endpoints the page actually uses. Inline onclick handlers are moved to JavaScript, and one small dynamic script receives a nonce generated for the response.
After critical screens have been verified, the same policy is switched to enforcement mode. The nonce value below is only a placeholder: in the application it is generated with cryptographic randomness for every response and inserted into both the header and the allowed element.
Content-Security-Policy:
default-src 'self';
script-src 'self' 'nonce-{náhodná-hodnota-pro-response}';
style-src 'self';
img-src 'self' https://images.example-cdn.test;
connect-src 'self' https://api.example.test;
object-src 'none';
frame-ancestors 'self';
base-uri 'self'
How it works
From the server response to the browser decision
This flow shows the simple decision the browser makes for every protected resource.
- The server sends the header For example, default-src sets the default sources, while specialised directives add scripts, images, or connections.
- The document requests a resource HTML, CSS, or JavaScript attempts to load a file, embed an iframe, or call an external API.
- The browser checks the rule It uses the specific directive, such as script-src or connect-src, or falls back to default-src.
- The resource is allowed or blocked An allowed resource loads; a violation is blocked in enforcement mode or only reported in report-only mode.
- The team verifies the impact Reports, the browser console, and functional tests help add legitimate sources without opening an unnecessarily broad exception.
Key concepts
Directives should have a narrow, explainable purpose.
A policy is clearer when every exception corresponds to an actual part of the application or integration.
default-src and resource types
default-src is the default restriction. script-src, style-src, img-src, font-src, and connect-src refine it for specific resource types. self means the same origin, not any secure domain.
Nonce and hash
A nonce is an unpredictable value generated anew for each relevant response, which the browser compares on an allowed script or style. A hash suits known, immutable inline content. Both approaches are more precise than a blanket unsafe-inline.
frame-ancestors and object-src
frame-ancestors controls who may embed the page in a frame; object-src can often be disabled with none. These are different boundaries from API loading or checks on a signed-in user.
Report-only
Content-Security-Policy-Report-Only collects violations but does not block the resource. It is used to verify the design before enforcement, not as the final security posture.
Benefits and limitations
Protection is only as precise as its rules.
Benefits
- restricting unauthorized scripts, resources, and some XSS paths
- traceable violations when an integration or template changes
- gradual rollout through report-only mode
- frame-ancestors as separate protection against unwanted page embedding
Risks and mistakes
- unsafe-inline or broad wildcards significantly reducing the value of the policy
- a static or reused nonce not being a secure nonce
- allowing an overly trusted third party expanding the attack surface
- an untested policy breaking payments, administration, or asset loading
Scope
Tighten the policy in small, measurable steps.
A practical process starts by auditing scripts, styles, CDNs, and integrations. Report-only mode reveals legitimate violations; inline handlers can then be converted to event listeners, inline scripts replaced with a nonce or hash, and the rules enforced gradually. The policy should be tested on critical paths, not only the home page.
CSP does not replace secure template design, CSRF protection, HTTPS, or authentication. On a page with many legacy inline scripts, restricting object-src and frame-ancestors may already provide value, while a strict script-src can be introduced gradually. The goal is not the longest possible header, but a verifiable minimum set of sources.
What to consider
The policy belongs in a tested operational contract.
Every exception should have a reason, an owner, and a review when the application or provider changes.
- begin with a report-only header and review actual violations
- use a nonce or hash for scripts instead of unsafe-inline
- set object-src none and consider frame-ancestors carefully
- restrict connect-src to known APIs and test both signed-in and signed-out paths
- check the header in automated HTTP tests and after integration changes
Common questions
What CSP addresses in practice
Does CSP replace output escaping?
No. Escaping and safe HTML handling prevent XSS from arising. CSP adds another layer that can restrict malicious content from running or loading.
Does report-only mode already provide protection?
No. The browser only reports violations. It is a safe way to discover the impact on legitimate functionality before enforcing the policy.
Can I simply allow unsafe-inline?
Technically yes, but scripts then lose much of the protection. It is better to replace inline code gradually with a nonce, hash, or external file.
Does CSP ensure that an API call is authorized?
No. connect-src restricts where a browser page may send requests. The API must independently validate the token, session, and permissions on the server.
How I approach security in practice
I assess security layers in the context of the entire application.
When designing and maintaining a website, I address client, API, data, and operational configuration boundaries together.