A policy is a string of directives separated by semicolons. Common directives include script-src, style-src, img-src, font-src, connect-src (for fetch and XHR and WebSocket), frame-src, and the catch-all default-src that applies to any type you did not name explicitly. Source values can be a specific host (https://api.stripe.com), a keyword like 'self' or 'none', a scheme like data:, or a cryptographic nonce or hash.
Inline scripts and styles are the hard part. The keyword 'unsafe-inline' allows them but defeats most of CSP's value, because injected inline scripts are exactly what XSS uses. The safe alternative is a nonce: the server generates a random value per response, puts it in the header as 'nonce-abc123', and adds nonce="abc123" to each legitimate inline script tag. The browser runs only tags carrying the matching nonce. Alternatively you can whitelist a specific inline block by its SHA-256 hash.
CSP supports a report-only mode via the Content-Security-Policy-Report-Only header. In this mode the browser does not block anything, it only sends JSON violation reports to a URL you specify with report-to. Teams use this to roll out a strict policy on a live site, watch what would have broken for a week or two, fix the legitimate violations, then switch to enforcing mode.
The strict-dynamic keyword changes how trust propagates. When a script you explicitly trusted (by nonce or hash) loads more scripts, those child scripts are trusted too, while plain host allowlists are ignored. This is the modern recommendation because long host allowlists are easy to bypass through open redirects or JSONP endpoints on otherwise trusted CDNs.