Score a Content Security Policy directive by directive and see whether it would actually stop an injected script.
script-src carries 30 of the 100 points because it is the only directive that decides whether an injected script executes, and unsafe-inline collapses it to 6 no matter how careful the host allow-list is. The remaining weight covers the directives that close the well-known bypasses: base-uri for injected <base> tags, object-src for plugin payloads and form-action for credential exfiltration. Most deployed policies are long, look strict and stop nothing, because one unsafe-inline or a missing base-uri hands the whole policy back to the attacker.
CSP Effectiveness
CSP score = script-src weight (30 nonce with strict-dynamic, 20 allow-list, 6 with unsafe-inline, 0 with unsafe-eval) + 12 enforced + 10 Trusted Types + 8 each for default-src, object-src, base-uri and frame-ancestors + 6 form-action + 6 reporting + 4 upgrade-insecure-requests = 100.
CSP score = script-src weight (30 nonce with strict-dynamic, 20 allow-list, 6 with unsafe-inline, 0 with unsafe-eval) + 12 enforced + 10 Trusted Types + 8 each for default-src, object-src, base-uri and frame-ancestors + 6 form-action + 6 reporting + 4 upgrade-insecure-requests = 100. script-src carries 30 of the 100 points because it is the only directive that decides whether an injected script executes, and unsafe-inline collapses it to 6 no matter how careful the host allow-list is. The remaining weight covers the directives that close the well-known bypasses: base-uri for injected <base> tags, object-src for plugin payloads and form-action for credential exfiltration.
Most deployed policies are long, look strict and stop nothing, because one unsafe-inline or a missing base-uri hands the whole policy back to the attacker.
This calculator takes 10 inputs: script-src strategy, Policy enforced, not Report-Only, require-trusted-types-for 'script', default-src 'self' or 'none', object-src 'none', base-uri 'self' or 'none', frame-ancestors set, form-action restricted to your own origins, report-to or report-uri configured, upgrade-insecure-requests. The pre-filled defaults are a realistic starting point — replace them with figures from your own environment for a result you can act on.
Because allow-lists are only as strong as the weakest file on every listed host. A JSONP endpoint, an open redirect or a hosted copy of AngularJS on any allow-listed CDN turns the policy into a bypass. Nonces bind execution to a per-response value the attacker cannot predict.