Skip to content

CSP Debugging Workshop: Explain Every Resource Decision

Compare an overbroad policy with a constrained solution, inspect nonce and report-only behavior, then prepare a real-browser rollout checklist.

Muhammad Azhar November 11, 2026 Editorial date: November 11, 2026 3 min read

A policy that blocks every script can break an application. A policy that permits every HTTPS script can leave the intended boundary much wider than the team expects. The useful engineering question is which required operations continue to work and which unapproved operations are prevented, with evidence for each decision.

This workshop uses sixteen fixed resources in a fictional application. You need to recognize origins and HTTP headers; no real site or security credential is required. Allow about 20 minutes and finish with an exported analysis plus a browser test plan.

Start from an inventory

Open the CSP policy workbench. Its scenario names the page origin, script CDN and API origin. Local CSS and images are needed, as is one inline bootstrap carrying the example nonce. An unapproved script origin, inline event handler, embedded object and external base URL should fail the scenario's expectations.

Run the starter policy and read every resource row. Do not begin by adding sources until the red results disappear. First distinguish a required resource that is blocked from an unwanted resource that is allowed. Those failures need opposite changes.

Repair one boundary at a time

  1. Replace broad script origins with the named CDN and same-origin source.
  2. Authorize the intended inline bootstrap with the provided teaching nonce. Verify that a different nonce and an event-handler attribute remain disallowed.
  3. Set the required image and connection sources without granting arbitrary HTTPS access.
  4. Inspect the base URL and form action decisions separately. They do not inherit the default source directive in this model.
  5. Compare your result with the revealed solution and explain any difference before exporting.

The solution meets all sixteen expectations in enforced mode. Now switch to report-only. The policy may still identify a violation, but the resource is not blocked by that report-only header. A report-only trial is an observation phase, not completed enforcement.

Try something the workbench cannot evaluate

Add 'strict-dynamic' to the script directive or introduce a directive outside the documented subset. The result must become unknown rather than claim that the application is secure. This deliberate refusal is part of the exercise: a convenient parser should never silently discard semantics that change a security conclusion.

The workbench does not execute requests or apply a CSP to its own page. It models one supplied header, a small source grammar and a fixed resource inventory. It does not model redirects, workers, multiple headers or browser compatibility. Keep that distinction in your decision record.

Turn the result into a rollout plan

Inventory the production application's resources during login, navigation, error handling and third-party integration flows. Configure reporting on a controlled environment and inspect reports without collecting unnecessary sensitive URLs. Separate extensions and browser noise from reproducible application violations.

Use a fresh, unpredictable nonce per response where your production policy relies on nonces; the constant in this exercise is not suitable for deployment. Verify that templates attach it only to intended elements, and examine how caching affects the rendered header and markup together. See MDN's CSP guide for nonce and deployment guidance.

Finally, test enforced headers in the supported browsers against the actual application. Keep a controlled rollback path. Record both a required workflow that still works and an intentionally unapproved resource that fails. A green sixteen-row teaching exercise is a useful reasoning checkpoint, not evidence that every resource on your application has been covered.

Sources and further reading