Serving a Header on Some Paths
The policy HeaderHawk builds from your script decisions (A policy from your decisions) is for your payment pages only. Your decisions cover only the scripts seen there, so served across the site it would block every script that runs only on your other pages. Scripts › Payment pages › Policy lists the paths, as your payment pages’ patterns.
One policy per page, once it is enforced
Section titled “One policy per page, once it is enforced”A browser enforces every Content-Security-Policy header a response
carries, and a script runs only if each of them allows it. So the two
phases are served differently:
- Report-only. Serve the payment-page header as
Content-Security-Policy-Report-Onlyon those paths, beside whatever your site already serves there. It blocks nothing; it reports what it would. - Enforcing. On those paths, serve the payment-page
Content-Security-Policyin place of your site-wide one. Served beside it, a pinned script whose host your site-wide policy does not list would still be blocked by that policy.
Keep the Reporting-Endpoints line your site already serves on those paths:
the policy’s report-to names it.
An add_header inside a location replaces every add_header the server
block sets, rather than adding to them, so repeat the ones the location still
needs.
server { add_header Reporting-Endpoints 'headerhawk="https://your-ingest-code.ingest.us.headerhawk.com/r"' always; add_header Content-Security-Policy "SITE_POLICY" always;
location /checkout/ { add_header Reporting-Endpoints 'headerhawk="https://your-ingest-code.ingest.us.headerhawk.com/r"' always; # While the payment-page policy is report-only, keep the site's: add_header Content-Security-Policy "SITE_POLICY" always; add_header Content-Security-Policy-Report-Only "PAYMENT_POLICY" always; # Once it is enforced, replace both lines above with: # add_header Content-Security-Policy "PAYMENT_POLICY" always; try_files $uri $uri/ /index.html; }}Apache
Section titled “Apache”Header always set in a <Location> replaces the value the server sets for
that header on those paths.
Header always set Content-Security-Policy "SITE_POLICY"
<Location "/checkout/"> # Report-only first: Header always set Content-Security-Policy-Report-Only "PAYMENT_POLICY" # Once it is enforced, use this instead: # Header always set Content-Security-Policy "PAYMENT_POLICY"</Location>Node.js (Express)
Section titled “Node.js (Express)”const PAYMENT_PATHS = ["/checkout/"];
app.use((req, res, next) => { const payment = PAYMENT_PATHS.some((path) => req.path.startsWith(path)); res.setHeader("Content-Security-Policy", SITE_POLICY); if (payment) { // Report-only first; once it is enforced, set Content-Security-Policy to // PAYMENT_POLICY instead of SITE_POLICY and drop this line. res.setHeader("Content-Security-Policy-Report-Only", PAYMENT_POLICY); } next();});Next.js
Section titled “Next.js”In next.config.js, when two entries match a path and set the same header,
the later one wins, so list the payment pages after the rest of the site.
module.exports = { async headers() { return [ { source: "/:path*", headers: [{ key: "Content-Security-Policy", value: SITE_POLICY }], }, { source: "/checkout/:path*", headers: [ // Report-only first; once it is enforced, use // { key: "Content-Security-Policy", value: PAYMENT_POLICY }. { key: "Content-Security-Policy-Report-Only", value: PAYMENT_POLICY }, ], }, ]; },};Cloudflare
Section titled “Cloudflare”A Response Header Transform Rule sets a header on the paths its filter
matches. Create one with the filter
starts_with(http.request.uri.path, "/checkout/") and the action Set
static: Content-Security-Policy-Report-Only to the payment-page policy
first, then Content-Security-Policy once it is enforced. Set replaces
any value your origin or an earlier rule sent, which is what the enforcing
phase needs.
Check what a payment page gets
Section titled “Check what a payment page gets”curl -sI https://www.example.com/checkout/ | grep -i content-security-policyWhile the payment-page policy is report-only, a payment page answers with your
site’s Content-Security-Policy and the payment-page
Content-Security-Policy-Report-Only. Once it is enforced, it answers with
exactly one Content-Security-Policy, the payment-page one, and any other page
still answers with your site’s. The Policy view says when your payment pages
first served the policy in each phase, from their reports or the daily scan.