1 Core concepts
Content Security Policy is a browser-enforced security layer that lets a site declare which content sources are trusted. By limiting where scripts, styles, images, frames, and other resources may come from, it reduces the opportunities for injected code to run. CSP is especially effective against cross-site scripting because it can block unexpected execution even when a flaw exists elsewhere in an application.
A policy is expressed as a set of directives, each controlling a specific class of resource or behavior. Browsers compare requested content against the policy and permit only what matches the approved rules. When a request or execution attempt does not fit the policy, the browser blocks it or records a violation, depending on the mode in use.
1.1 Purpose and security goals
The main purpose of CSP is to narrow the attack surface of a web page. It helps prevent malicious scripts from loading, limits unauthorized connections to remote services, and can restrict framing or form submission to known destinations. These controls are useful for reducing the impact of compromised third-party content, accidental injection, and some classes of data exfiltration.
CSP is not a complete replacement for secure coding practices. It works best as a defensive layer alongside input validation, output encoding, secure cookie settings, and careful dependency management. Its value lies in constraining what a page can do, even when the page contains user-controlled or externally supplied content.
1.2 Browser enforcement model
Browsers enforce CSP locally while processing the document. When the page tries to load a resource or execute code, the browser checks the relevant directive and determines whether the action is allowed. This means the policy is applied consistently by the client rather than relying on server-side monitoring alone.
The enforcement model is declarative: the server states what is acceptable, and the browser handles compliance. This approach is useful because it applies before a blocked resource runs or renders, which can stop harmful behavior early. The model also supports reporting so that site operators can learn about attempted violations and adjust the policy.
1.3 Policy delivery methods
CSP policies are usually delivered in the page response, where the browser can read them before or during document processing. The two common delivery methods are HTTP headers and HTML meta tags. Headers are generally preferred because they are applied earlier and are better suited for complete enforcement.
1.3.1 HTTP Content-Security-Policy header
The primary delivery mechanism is the Content-Security-Policy HTTP response header. It can be set by the web server or application layer and applies to the delivered document. Because the browser sees the header at the start of processing, this method is the most reliable for controlling the page from the outset.
Headers support multiple directives in one policy string and can be used with both enforce and report-only modes. They are also appropriate for site-wide deployment, including pages that do not contain editable HTML markup.
1.3.2 HTML meta tag delivery
CSP can also be specified with a <meta> element in the document head. This option is useful when server headers are difficult to configure, but it is less flexible and typically less robust than header delivery. The browser only applies the policy after encountering the meta tag, so earlier content may not be covered in the same way.
Meta-delivered policies are commonly used for simple deployments or legacy systems. They are best treated as a secondary option when HTTP headers are unavailable.
1.4 Resource origin restrictions
At the core of CSP is the idea of origin restriction. A policy may permit resources only from the same origin, specific trusted domains, or carefully defined schemes and paths. This helps prevent a page from loading code or data from unexpected places.
Origin restrictions can be broad or narrow depending on the directive. Some rules allow only self-hosted resources, while others permit selected content delivery networks, APIs, or embedded services. The tighter the policy, the smaller the set of sources that can influence the page.
2 Policy directives
CSP directives govern different categories of behavior, from fetching external assets to controlling navigation and embedded content. Each directive affects a specific part of browser behavior, and a single policy may contain many directives at once. When a directive is absent, its behavior may fall back to another rule such as default-src, depending on the resource type.
2.1 Fetch directives
Fetch directives control where the browser may retrieve resources from. They are among the most visible parts of CSP because they regulate scripts, styles, images, fonts, connections, media, and frames. These directives are central to limiting unwanted loading behavior.
2.1.1 default-src
default-src provides a fallback source list for many resource types when a more specific directive is not present. It is often used as a baseline rule that starts from a restrictive position, such as allowing only same-origin content. More specific directives can then override the default for individual resource categories.
Because it influences multiple kinds of requests, default-src is often the first directive considered when designing a policy. A careful default can simplify configuration and reduce accidental broad allowances.
2.1.2 script-src
script-src controls JavaScript execution and script loading. It is one of the most important directives because scripts are a primary vehicle for client-side attacks. It can limit external script hosts, inline script blocks, event handler behavior, and certain dynamic execution features.
A strong script-src policy often relies on nonces, hashes, or both. This allows legitimate scripts while rejecting injected code that lacks the approved marker.
2.1.3 style-src
style-src governs CSS resources and inline styling. It can reduce the risk of style injection and prevent unexpected stylesheet loading from untrusted sources. Although styles are not the same as scripts, they can still be used in ways that influence rendering, data leakage, or user interaction.
This directive is commonly paired with restrictions on inline styles and approved style hosts. It helps ensure that page appearance remains under site control.
2.1.4 img-src
img-src defines where images may be loaded from. This is useful for preventing tracking pixels, malicious image URLs, or unexpected remote fetches. It can include same-origin content, selected image hosts, or data and blob URLs if explicitly allowed.
While images are generally lower risk than executable resources, controlling them can still matter for privacy, bandwidth, and consistency. The directive also affects iconography and visual assets used by the page.
2.1.5 font-src
font-src restricts font files. Fonts can be loaded from the site itself or from chosen providers, depending on the policy. Limiting this source list helps avoid unexpected external dependencies and can support tighter control over presentation.
Although fonts are not executable in the usual sense, they still represent network activity and a possible point of leakage if broadly permitted. A precise font policy can improve both security and performance predictability.
2.1.6 connect-src
connect-src governs network connections initiated by scripts and related browser features. It affects fetch requests, XMLHttpRequest, WebSocket connections, and other forms of client-side communication. This directive is important for limiting data exfiltration and constraining where application code may send information.
A narrow connect-src rule helps ensure that browser-side code communicates only with approved APIs and services. It is especially useful in applications that handle sensitive user data.
2.1.7 media-src
media-src controls audio and video resources. It limits where the browser can retrieve media files from and can be used to avoid untrusted streaming hosts. In many applications this directive is not heavily customized, but it remains relevant for sites that embed multimedia content.
The directive can also matter for bandwidth management and source tracking. It provides a straightforward way to keep media loading aligned with the rest of the policy.
2.1.8 frame-src
frame-src regulates which origins may be loaded into frames or iframes. This helps site operators control embedded content, especially when third-party widgets or interactive panels are used. Restricting frames reduces the chance of loading unwanted remote pages inside the application.
This directive is distinct from controls over who may frame the site itself. It concerns the frames the page loads, rather than the pages that load the page.
2.2 Document and navigation directives
Document and navigation directives influence how the page interacts with its own structure, forms, and embedding environment. These rules are important for preventing subtle redirection, form abuse, and framing-related risks. They help define the surrounding document behavior rather than just resource fetching.
2.2.1 base-uri
base-uri restricts the <base> element, which can alter how relative URLs are resolved. By limiting allowed base URLs, the policy prevents attackers from changing link and resource resolution in ways that could redirect requests or alter page behavior. This is a relatively small directive with an important protective role.
2.2.2 form-action
form-action limits where forms may submit data. It helps prevent unauthorized form posts and reduces the risk that user-entered information will be sent to unapproved destinations. This directive is especially useful for login pages, checkout flows, and other forms that carry sensitive data.
2.2.3 frame-ancestors
frame-ancestors specifies which sites may embed the page in a frame. It is a defense against unwanted framing and clickjacking-style abuse. Unlike frame-src, this directive controls who may place the document inside a frame rather than what the document itself loads.
2.2.4 navigate-to
navigate-to limits the destinations to which a page may initiate navigation. It can help prevent unexpected redirects or scripted navigation to unapproved locations. This directive is useful in applications that perform redirects or open external links based on user actions or code paths.
2.3 Execution and embedding controls
Execution and embedding controls affect browser features that can load executable or plugin-like content. These directives often close off older or less common capabilities that are not needed by modern applications. They can provide an additional layer of safety beyond basic fetch rules.
2.3.1 object-src
object-src governs plugin content such as object, embed, and related elements. In many modern policies, it is set very narrowly or disabled entirely because plugin-based loading is rarely required. Restricting this category helps remove a legacy pathway for content injection.
2.3.2 worker-src
worker-src controls the origins from which web workers and similar background execution contexts may be created. Workers can load scripts and process data off the main thread, so limiting their sources can be important for security. This directive helps ensure that background code comes from trusted locations.
2.3.3 manifest-src
manifest-src restricts the origin of web app manifests. These files describe installable application behavior and related metadata. Controlling them helps prevent unexpected manifest loading from untrusted sources.
2.3.4 upgrade-insecure-requests
upgrade-insecure-requests tells the browser to rewrite insecure HTTP requests to HTTPS when possible. This reduces mixed-content exposure and helps modernize older content references. It is often used in sites transitioning toward fully encrypted delivery.
2.3.5 block-all-mixed-content
block-all-mixed-content instructs the browser to block insecure subresources when the page is served over a secure connection. This is a stronger stance than automatic upgrading in situations where insecure fallback should not be tolerated. It helps preserve the integrity of the secure page context.
3 Script security mechanisms
Script control is the most security-sensitive part of CSP because scripts can modify the document, read data, and initiate network requests. CSP offers several mechanisms for allowing legitimate scripts while denying injected ones. These mechanisms are often combined for stronger protection.
3.1 Nonces
A nonce is a random value generated for a specific response and included both in the policy and in permitted script tags. Browsers allow only scripts carrying the matching nonce, which makes it difficult for injected markup to execute. Nonces are especially useful when a page must contain dynamic inline scripts.
Because the value changes per response, a nonce-based policy avoids the need to trust a fixed set of inline blocks. This approach is widely used in modern applications with server-rendered content or templated pages.
3.2 Hashes
Hashes allow specific inline script or style content by matching the exact cryptographic digest of the code. If the content changes, the hash no longer matches and the browser blocks it. This makes hashes useful when a page contains a small number of stable inline snippets.
Hashes are often favored for static content or carefully controlled initialization code. They provide precise approval without relying on a per-request random value.
3.3 unsafe-inline and unsafe-eval
unsafe-inline and unsafe-eval are policy keywords that relax script restrictions. unsafe-inline permits inline script execution, while unsafe-eval allows string-to-code operations such as certain dynamic evaluation patterns. Both weaken CSP’s protective value because they open paths that attackers may exploit more easily.
These allowances are sometimes used for compatibility with older code or libraries, but they are generally avoided in stronger deployments. Reducing dependence on them is an important step toward a more resilient policy.
3.4 strict-dynamic
strict-dynamic changes how trust is propagated for scripts that are explicitly approved by nonce or hash. Once a trusted script is allowed, scripts it loads may also be accepted under the policy’s dynamic trust model, reducing the need to enumerate every downstream host. This can simplify policies in applications that use loader scripts or modular bootstrapping.
The mechanism is powerful but should be used carefully. It is most effective when the bootstrap scripts themselves are tightly controlled.
3.5 Trusted Types integration
Trusted Types is a browser security feature that works with CSP to limit dangerous DOM injection sinks. Instead of allowing arbitrary strings to flow into sensitive APIs, the application must pass values created through approved policies. This can reduce the risk of DOM-based cross-site scripting in complex client-side code.
When integrated with CSP, Trusted Types adds another layer of checking beyond source restrictions. It is particularly helpful in applications that rely heavily on JavaScript frameworks and dynamic DOM manipulation.
4 Policy modes and reporting
CSP can either actively block violations or simply observe them. This flexibility allows site operators to test policies before enforcing them and to collect useful information about blocked behavior. Reporting is a practical part of deployment because it reveals where policies are too strict or where unexpected code paths exist.
4.1 Enforce mode
In enforce mode, the browser blocks actions that violate the policy. This is the standard operational mode for protecting a site once the policy has been tested. Enforcement can stop scripts from running, prevent resources from loading, and deny disallowed navigations or form submissions.
Because it affects real user sessions, enforce mode should be introduced carefully. A policy that is too strict can break legitimate functionality, so testing is important before broad deployment.
4.2 Report-only mode
Report-only mode records violations without blocking them. This allows administrators to observe how a proposed policy would behave in practice. It is commonly used during policy development, migration, and tuning.
This mode is valuable for identifying resources that must be added to the allowlist or code paths that should be removed. It provides visibility without disrupting the user experience.
4.3 Violation reports
Violation reports describe which directive was triggered, what resource was affected, and where the event occurred. They help operators understand whether a block was expected, accidental, or indicative of malicious behavior. Reports can be sent to a monitoring system or an endpoint chosen by the site owner.
4.3.1 report-uri
report-uri is a reporting directive that sends violation data to a specified URL. It has been used widely in CSP deployments, especially in earlier implementations. Although it remains familiar, newer reporting mechanisms are often preferred in modern setups.
4.3.2 report-to
report-to integrates CSP with the browser reporting framework. It allows reports to be grouped and sent to designated endpoints using a structured configuration. This approach supports more flexible and standardized handling of security telemetry.
4.4 Reporting endpoints
Reporting endpoints are the destinations that receive violation data. They may forward reports to logs, dashboards, alerting systems, or security analytics tools. A well-designed endpoint makes it easier to identify repeated policy failures and distinguish normal user activity from suspicious patterns.
Because reports can contain information about page structure and blocked URLs, endpoints should be treated as part of the security infrastructure. They should be monitored and maintained with appropriate care.
5 Implementation and deployment
Deploying CSP successfully requires planning, testing, and gradual refinement. A policy that looks simple on paper may interact with application frameworks, third-party widgets, or legacy code in unexpected ways. Effective implementation usually begins with observation and ends with carefully enforced rules.
5.1 Designing a policy
Policy design starts with identifying the resources a page genuinely needs. The goal is to allow only those sources and capabilities that are necessary for the application to function. Many deployments begin with a restrictive baseline and then add exceptions only when justified.
A clear design also considers different page types. A login page, content page, and admin interface may require different allowances. Separating these cases can lead to stronger and more maintainable policies.
5.2 Allowlisting external resources
External resources should be permitted only when there is a strong operational need. This includes scripts, styles, fonts, analytics tools, and embedded services. Each added source broadens the trust boundary, so the list should remain as small as practical.
When allowlisting is required, exact hostnames and limited schemes are usually preferable to broad wildcards. Narrow matching reduces the chance that unrelated content will become trusted by mistake.
5.3 Handling inline code
Inline code often causes the most difficulty during CSP deployment. Many older pages depend on inline scripts or styles, but these patterns are harder to secure because they blur the boundary between content and executable logic. Nonces and hashes provide a safer alternative than blanket inline permission.
Migration may involve moving inline blocks into external files, using templating systems to add nonces, or restructuring initialization code. Over time, reducing inline content tends to make policies simpler and more robust.
5.4 Migrating legacy applications
Legacy applications often have mixed patterns of old and new web practices. They may include inline event handlers, broad resource hosts, or plugin-style elements that do not fit modern CSP well. Migration usually proceeds in stages, beginning with report-only mode and a conservative policy.
During migration, teams often discover dependencies that were not previously documented. CSP reports can reveal these hidden assumptions and help guide code cleanup. The process may take time, but it usually improves maintainability as well as security.
5.5 Framework and library considerations
Frameworks and client-side libraries can influence how CSP is configured. Some generate inline code, use dynamic loading, or rely on patterns that require specific allowances. Understanding the framework’s behavior is important before finalizing the policy.
Library updates may also change CSP compatibility over time. A policy that works for one version may need adjustment for another, so deployment should include ongoing review rather than a one-time configuration step.
6 Security limitations and bypasses
CSP is a strong defense, but it is not invulnerable. Its effectiveness depends on correct configuration, browser behavior, and the security of the application itself. Weak policies or permissive exceptions can reduce protection substantially.
6.1 Misconfigurations
A common weakness is an overly broad policy. Allowing too many hosts, using wildcard patterns, or enabling inline execution without strong controls can leave large gaps. Misapplied directives may also give a false sense of safety if they do not cover the relevant resource type.
Another issue is inconsistent deployment across pages or environments. If some parts of a site lack the intended policy, attackers may target the weaker entry point. Careful review and uniform rollout are therefore important.
6.2 Browser compatibility issues
CSP support differs somewhat across browser versions and feature sets. Newer directives or related mechanisms may not behave identically everywhere. This can affect how a policy is interpreted and whether certain protections are available.
Compatibility concerns are especially important when using advanced features such as strict-dynamic, Trusted Types, or newer reporting options. Testing across target browsers helps avoid surprises.
6.3 Common bypass techniques
Bypasses often rely on weaknesses outside CSP itself, such as trusted script loading paths, permissive allowlists, or application logic that already grants too much control. If an attacker can influence a whitelisted source or exploit a trusted loader script, CSP may be less effective.
Some bypasses also stem from broad use of unsafe-inline, unsafe-eval, or very open resource origins. The more the policy resembles a default-open configuration, the easier it is to work around.
6.4 Interaction with other web defenses
CSP works best when combined with other defenses rather than used alone. Input validation and output encoding reduce the chance of injection, while secure cookies and same-origin protections limit the impact if an attack succeeds. Subresource Integrity can further protect external assets by verifying their contents.
These layers complement one another. CSP constrains behavior, while other mechanisms help ensure that the page receives and processes trustworthy data in the first place.
7 Best practices
Effective CSP deployment depends on discipline and iteration. A policy should be as narrow as practical while still supporting the application’s legitimate behavior. Good practices focus on minimizing trust, improving observability, and updating the policy as the site evolves.
7.1 Starting with a restrictive baseline
A strong policy usually begins with a minimal default source list and explicit allowances only where needed. This approach reduces accidental exposure and makes the policy easier to reason about. It also highlights unexpected dependencies early in the process.
Starting narrowly does not mean deploying blindly. A measured rollout with reporting helps balance safety and usability.
7.2 Using nonces or hashes
Nonces and hashes are preferred for allowing inline code when inline code cannot be fully removed. They provide a more precise trust model than broad inline permission. Where possible, they should be combined with other script restrictions for stronger control.
These mechanisms are especially useful for bootstrapping code and small, stable snippets. They support secure operation without requiring a site to trust all inline content.
7.3 Minimizing broad source allowances
Policies should avoid unnecessary wildcards and overly general trust rules. Broad allowances can unintentionally include content that was not intended to be trusted, such as subdomains or shared hosting environments. Narrow, explicit source lists are usually safer.
Reducing allowances also makes policy maintenance easier. When trust is limited to a small set of sources, changes are easier to audit and understand.
7.4 Testing and iteration
A CSP should be tested in report-only mode before full enforcement. This reveals blocked resources and compatibility problems without affecting live behavior. Iterative tuning is often needed because real-world applications may contain hidden dependencies.
Testing should cover common user flows as well as edge cases. A policy that works on one page or in one browser may still need refinement elsewhere.
7.5 Monitoring violations
Ongoing monitoring helps detect regressions and suspicious activity. Violation reports can show when a new feature needs policy updates or when unexpected code attempts to run. This makes CSP not just a blocking tool but also a source of security insight.
Regular review of reports can improve both security posture and application quality. Patterns in violations may reveal outdated code, third-party changes, or attempted abuse.
8 Related standards and ecosystem
CSP is part of a broader set of web platform protections. It addresses one layer of browser risk, while other standards focus on integrity, origin boundaries, resource sharing, and permission management. Understanding these related technologies helps place CSP in context.
8.1 Subresource Integrity
Subresource Integrity verifies that an external resource matches an expected cryptographic hash. It is commonly used for scripts and styles loaded from third-party locations. While CSP restricts where a resource may come from, SRI checks that the resource has not been altered.
The two mechanisms complement each other well. CSP limits the source, and SRI confirms the content.
8.2 Same-origin policy
The same-origin policy is a foundational browser rule that limits how documents from different origins interact. It restricts access to data, DOM content, and certain APIs across origin boundaries. CSP builds on this model by adding finer-grained controls over resource loading and execution.
Together, the two mechanisms help shape browser isolation. Same-origin policy is broad and structural, while CSP is more configurable and application-specific.
8.3 Cross-Origin Resource Sharing
Cross-Origin Resource Sharing is a protocol that lets servers declare which cross-origin requests are permitted. It is used to relax same-origin restrictions in controlled situations, especially for APIs. CSP complements CORS by limiting where a page may connect, while CORS controls whether the server will accept the request and expose the response.
These are related but distinct tools. A site may allow a request under CORS while still blocking it under CSP, or vice versa, depending on policy design.
8.4 Permissions Policy
Permissions Policy controls access to browser features such as camera, microphone, geolocation, and other powerful capabilities. It is not a replacement for CSP, since it addresses feature access rather than content loading. However, both standards help constrain what a page can do in the browser.
Used together, they provide layered control over execution, resource use, and sensitive device access. This makes them valuable components of a modern security strategy.