Document Workflow
Analyze a Content-Security-Policy header before deployment
Capture the deployed CSP field, distinguish enforcement from Report-Only, review first-wins duplicates and cumulative policies, and test browser behavior before release.
Written and tested by SimpleWebUtilsPublished: Reviewed:
How this workflow was checked
For “Review a nonce-based policy without treating image data as script risk”, we entered the documented fixture in CSP Header Analyzer and followed “Reduce the capture before sharing” before “Interpret sources in their effective context”. We compared the browser result with the stated output, then reviewed “Capturing the origin instead of the edge” and “Editing a duplicate that is ignored” as separate failure boundaries.
The parser kept the nonce and 'strict-dynamic' relationship intact, reported no high-risk finding, and treated img-src data: as an item to justify rather than a script-source failure.
Problem
Content-Security-Policy is not one universal allowlist. A response can carry an enforced field, a Report-Only field, several comma-delimited policies, or repeated fields added by the application, reverse proxy, and CDN. Inside each policy, the first directive with a given name is effective and a later duplicate is ignored; across policies, restrictions apply cumulatively. A token such as unsafe-inline also cannot be graded without its effective directive, nonce or hash sources, strict-dynamic behavior, and browser compatibility context. Looking only at a long header string can therefore produce the wrong fix: loosening a policy that never blocked anything, editing a duplicate the browser ignores, or allowing a broad source when the real failure came from another route. A useful review starts with the final deployed response, removes unrelated secrets, parses one exact CSP field, maps findings to browser violations, tests affected routes and resource types, and captures the edge response again after configuration propagation.
Sources and standards
These authoritative references define the formats or security boundaries used in this workflow. Tool-specific verification is documented separately above.
- Content Security Policy Level 3
World Wide Web Consortium (W3C)
When to use this
- A console or CSP report names a blocked script, image, font, frame, worker, form action, or API connection.
- A Content-Security-Policy-Report-Only candidate is being considered for enforcement.
- Application, proxy, and CDN layers may be appending duplicate fields or directives.
- A nonce, hash, strict-dynamic, wildcard, data:, blob:, or HTTP source needs context-aware review.
- A release checklist needs repeatable before-and-after evidence from the final deployed response.
Steps
- Step 1
Capture the final response field
Open the exact affected route in DevTools or use curl -I for one response and curl -IL when redirects matter. Copy the final Content-Security-Policy or Content-Security-Policy-Report-Only field after the CDN and reverse proxy have modified it.
- Step 2
Reduce the capture before sharing
Keep the CSP field name and full value, including commas and semicolons. Remove cookies, Authorization, signed report endpoint parameters, internal hostnames that are not needed for review, and every unrelated response header.
- Step 3
Parse policies and first directives
Paste one CSP field into CSP Header Analyzer. Confirm enforcement disposition, policy count, recognized and unknown directives, then inspect duplicate findings. A later duplicate inside one policy does not override the first.
- Step 4
Interpret sources in their effective context
Review unsafe-inline with nonce, hash, strict-dynamic, and more-specific directive fallback in mind. Treat script and object wildcards more urgently than a deliberate image data: source, and investigate invalid or legacy values instead of deleting them blindly.
- Step 5
Map each symptom to browser evidence
Reproduce the route and action that generated the violation. Match script and style failures to their effective fallback chain, API and WebSocket failures to connect-src, frames to frame-src or frame-ancestors, workers to worker-src, and submissions to form-action.
- Step 6
Change the narrowest policy owner
Fix the application, middleware, proxy, or CDN rule that owns the effective directive. Prefer a nonce, hash, or exact trusted origin when appropriate, preserve Report-Only observation during rollout, and avoid adding wildcard or unsafe tokens merely to silence the console.
- Step 7
Retest routes and recapture the edge
Exercise normal, error, authentication, embed, worker, and third-party flows in supported browsers. Review violation volume, then capture the final response again after caches and configuration propagation. Store the sanitized before-and-after fields with the release record.
Example
Review a nonce-based policy without treating image data as script risk
Input
Content-Security-Policy: default-src 'self'; script-src 'nonce-AbCd12_-' 'strict-dynamic'; style-src 'self'; img-src 'self' https: data:; connect-src 'self' https://api.example.com; object-src 'none'; base-uri 'none'; frame-ancestors 'none'; report-to csp-endpointOutput
Disposition: enforced
Policies: 1
High-risk findings: 0
Review: img-src data: is informational and must be justified by image behavior; the example nonce cannot prove runtime nonce generation or element matching.Common mistakes
Capturing the origin instead of the edge
A reverse proxy or CDN can append, combine, or replace CSP fields. Reviewing an application-server value alone may not represent what the browser receives.
Editing a duplicate that is ignored
Within one policy the first directive name wins. Changing only a later duplicate can leave browser behavior untouched while making configuration harder to understand.
Treating Report-Only as enforcement
Report-Only generates observations without blocking. A clean candidate does not protect the page until an enforced field is deployed and verified.
Reading multiple policies as alternatives
Every enforced policy must allow a request. Adding another policy can tighten behavior but cannot loosen a restriction in an existing policy.
Fixing reports with broad exceptions
Adding *, unsafe-inline, unsafe-eval, data:, or an entire scheme can hide the symptom while expanding capability. Trace the exact dependency and its owner first.
FAQ
Why did changing the second script-src directive do nothing?
The CSP parsing algorithm keeps the first directive of a given name within one policy and ignores later duplicates. Remove the duplicate and change the actual first directive at its owning layer.
Can a second CSP policy loosen the first one?
No. Enforced policies apply cumulatively, so a resource must pass every applicable policy. A second policy can only preserve or further restrict effective capability.
Is unsafe-inline always active when the text appears?
No. In relevant effective source lists, nonce or hash sources prevent unsafe-inline from allowing all inline behavior; strict-dynamic also changes modern script handling. Browser compatibility still needs testing.
Should every policy contain default-src?
Not necessarily. default-src is a fallback for fetch directives. A policy with deliberate explicit coverage may omit it, but every resource type and fallback chain used by the app must then be reviewed.
Can the analyzer fetch my site or verify runtime nonces?
No. It parses bounded pasted text locally. Use DevTools, curl, browser tests, and server-side review to verify the deployed field, nonce generation, element matching, reports, and route behavior.
What evidence should be kept for release review?
Keep sanitized final-response fields, the parsed report, representative violation samples, tested routes and browsers, configuration owner, deployment time, and a post-propagation recapture.