← Debugging Guides

阅读中文版本

CSP — Refused to Load the Script Because It Violates the Policy

Debug Content Security Policy violations from console reports and report-only mode, read the directive that fired, and fix the policy or the resource delivery.

intermediatedebuggingsecuritycspbrowser

Symptoms

  • Console shows Refused to load the script because it violates the following Content Security Policy directive: script-src 'self'
  • Styles, images, or XHR calls fail with analogous connect-src, style-src, or img-src violations after a CSP rollout
  • Inline event handlers and eval-based libraries stop working under the new policy

Possible causes

  • The CSP whitelist omits the origin serving scripts, styles, or API calls
  • Inline scripts or event handlers were left in place without unsafe-inline or nonces
  • A third-party widget loads from an origin nobody added to the policy
  • The header order or multiple CSP headers intersect, making the effective policy stricter than intended

Diagnosis steps

Read the exact violation in the console

DevTools → Console → filter by "Content Security Policy"

Interpretation

Each violation names the directive and the blocked URL — the precise pairing of rule and resource that must be reconciled.

Inspect the effective headers

curl -sI https://app.example.com | grep -i content-security-policy

Interpretation

Multiple CSP headers intersect (the strictest wins); one policy with many directives is easier to reason about than several competing headers.

Dry-run with report-only first

Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report

Interpretation

Report-only mode logs violations without blocking, letting you collect the full violation set before enforcing anything.

Root cause

A Content Security Policy is enforced by the browser as a whitelist of sources per resource type. Any resource outside the directive whitelist — script, style, connection, image, font — is refused at load time. The policy and the actual delivery graph of the page disagree about which origins are legitimate.

Fix

Collect violations in report-only mode, add the origins you actually use per directive, replace inline scripts with nonces or hashes instead of unsafe-inline where possible, and deploy enforcement only after the report stream is clean.

Risk note

Adding unsafe-inline or a wildcard domain to silence one error permanently weakens the policy. Use nonces and specific origins.

Verify the fix

With enforcement on, the console shows zero violations, all functionality works, and the report endpoint receives no new reports during a full user journey.

Symptom walkthrough

The console violation is a complete incident report:

Refused to load the script from
'https://cdn.partner.example.com/widget.js'
because it violates the following Content Security Policy
directive: "script-src 'self'"

Rule: script-src ‘self’. Resource: a partner CDN. The disagreement is the entire bug. The sibling violations follow the same shape for other resource types — connect-src blocks the XHR, style-src blocks the inline style attribute, img-src blocks the tracking pixel. Read them as a list of (directive, origin) pairs your policy must explicitly allow or your delivery must relocate.

Fix in practice

Stage the rollout with report-only while you collect the real list:

Content-Security-Policy-Report-Only:
  default-src 'self';
  script-src 'self' 'nonce-r4nd0m' https://cdn.partner.example.com;
  connect-src 'self' https://api.example.com;
  style-src 'self' 'nonce-r4nd0m';
  report-uri /csp-report;

Then enforce the same policy once reports go quiet:

Content-Security-Policy:
  default-src 'self';
  script-src 'self' 'nonce-r4nd0m' https://cdn.partner.example.com 'strict-dynamic';
  report-uri /csp-report;

Serve the nonce with each response and mark inline scripts with it — nonce-per-response keeps inline capability without the blanket unsafe-inline. And instrument the report endpoint: violations after deployment become a monitoring stream, not user-reported breakage.