Skip to content
MDView as Markdown

Nginx

Adding a CSP header in Nginx is one line. Keeping it on every response is the part that catches people out, because add_header has an inheritance rule that quietly discards inherited headers - and it fails silently, so the first sign of trouble is usually a policy that is missing on exactly the pages you cared about.

What Nginx gives you

  • add_header name value [always]; in http, server, location and if in location contexts.
  • Values that can contain variables, so a policy can vary by request.
  • add_header_inherit (Nginx 1.29.3 and later) with on, off and merge, to control the inheritance behaviour explicitly.

Setting the header

Your URLs come from the Setup page:

add_header Content-Security-Policy-Report-Only "default-src 'none'; script-src 'report-sha256'; form-action 'none'; frame-ancestors 'none'; report-uri https://abc123.report-uri.com/r/d/csp/reportOnly; report-to default" always;
add_header Reporting-Endpoints 'default="https://abc123.report-uri.com/a/d/g"' always;
add_header Report-To "{\"group\":\"default\",\"max_age\":31536000,\"endpoints\":[{\"url\":\"https://abc123.report-uri.com/a/d/g\"}],\"include_subdomains\":true}" always;

The Reporting-Endpoints and Report-To headers tell the browser where report-to default sends reports, including the CSP Integrity reports that 'report-sha256' turns on.

That is the same starting policy we recommend for the CSP Wizard, and report-only blocks nothing.

Things to watch for

  • The inheritance rule is the big one. A child block inherits add_header directives from its parent only if the child defines none of its own. Add a single unrelated add_header inside a location and every header inherited from the server or http block - including your CSP - disappears from responses for that location. On 1.29.3 and later, add_header_inherit merge; fixes it. Before that, you have to repeat the directives in every block that defines any.
  • Without always, the header is only added to a specific set of status codes (200, 201, 204, 206 and the 301/302/303/304/307/308 redirects). Error responses go out with no policy. Use always.
  • Nginx cannot generate a per-request nonce on its own. Nonce-based policies need the application, or a module such as njs or Lua. Allowlist and hash-based policies are fine here.

Official documentation

Nginx - ngx_http_headers_module

Start Monitoring with Report URI

Already using us for CSP? Find your CSP reporting directives on Setup, or view your CSP reports.

New to Report URI? Create an account and grab your CSP reporting directives from the Setup page. Prefer a guided setup? The CSP Wizard builds a policy from your reports automatically once you're signed in.

Start your free trial