Skip to content

Node.js CSP Integration

Add CSP headers to Express, Koa, Fastify, or any Node.js HTTP server.

  • Node.js 18+
  • An HTTP framework (Express, Koa, Fastify, etc.)
const express = require("express");
const app = express();
// CSP Middleware
app.use((req, res, next) => {
res.setHeader(
"Content-Security-Policy-Report-Only",
"default-src 'self'; report-uri https://ingest.headerhawk.com/csp/YOUR_SITE_ID"
);
next();
});
app.listen(3000);

Helmet provides a cleaner API:

Terminal window
npm install helmet
const express = require("express");
const helmet = require("helmet");
const app = express();
app.use(
helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:", "https:"],
reportUri: ["https://ingest.headerhawk.com/csp/YOUR_SITE_ID"],
},
reportOnly: true, // Remove this line to enforce
})
);
app.listen(3000);
const fastify = require("fastify")();
fastify.addHook("onSend", (request, reply, payload, done) => {
reply.header(
"Content-Security-Policy-Report-Only",
"default-src 'self'; report-uri https://ingest.headerhawk.com/csp/YOUR_SITE_ID"
);
done();
});
fastify.listen({ port: 3000 });
const Koa = require("koa");
const app = new Koa();
app.use(async (ctx, next) => {
ctx.set(
"Content-Security-Policy-Report-Only",
"default-src 'self'; report-uri https://ingest.headerhawk.com/csp/YOUR_SITE_ID"
);
await next();
});
app.listen(3000);

Generate policies based on request context:

const crypto = require("crypto");
app.use((req, res, next) => {
const nonce = crypto.randomBytes(16).toString("base64");
res.locals.nonce = nonce;
res.setHeader(
"Content-Security-Policy-Report-Only",
`default-src 'self'; script-src 'self' 'nonce-${nonce}'; report-uri https://ingest.headerhawk.com/csp/YOUR_SITE_ID`
);
next();
});

Then in your templates:

<script nonce="<%= nonce %>">
// Your inline script
</script>
import express, { Request, Response, NextFunction } from "express";
const app = express();
const cspMiddleware = (req: Request, res: Response, next: NextFunction) => {
const policy = [
"default-src 'self'",
"script-src 'self'",
"style-src 'self' 'unsafe-inline'",
"img-src 'self' data: https:",
"report-uri https://ingest.headerhawk.com/csp/YOUR_SITE_ID",
].join("; ");
res.setHeader("Content-Security-Policy-Report-Only", policy);
next();
};
app.use(cspMiddleware);
app.listen(3000);
  1. Check the header is being set: curl -I http://localhost:3000
  2. Verify the site ID is correct
  3. Check for typos in the report-uri

The Header Hawk ingestion endpoint handles CORS automatically. If you see CORS errors, verify you’re using the correct endpoint URL.