import { pino } from 'pino'; import { HttpConfig } from './server'; import * as sch from '../utilities/json-schema'; import { FastifyReply, FastifyInstance, FastifyRequest, RouteShorthandOptions } from 'fastify'; export const default_policy = `default-src 'self'`; export const csp_report_schema = sch.obj({ 'csp-report': sch.obj({ 'document-uri': sch.str(), 'referrer': sch.str(), 'blocked-uri': sch.str(), 'violated-directive': sch.str(), 'original-policy': sch.str(), 'disposition': sch.str(), 'effective-directive': sch.str(), 'script-sample': sch.str(), 'status-code': sch.int(), }, { additionalProperties: true }) }); export interface CSPReport { 'csp-report': { 'document-uri': string; 'referrer': string; 'blocked-uri': string; 'violated-directive': string; 'original-policy': string; 'disposition': string; 'effective-directive': string; 'script-sample': string; 'status-code': number; }; } export interface Dependencies { logger: pino.Logger; } export function register_csp_report_endpoint(http_server: FastifyInstance, conf: HttpConfig, { logger }: Dependencies) { const opts: RouteShorthandOptions = { schema: { response: { 204: { }, }, body: csp_report_schema } }; type Req = FastifyRequest<{ Body: CSPReport; }>; http_server.post('/.csp-report', opts, async (req: Req, res) => { logger.warn(req.body['csp-report'], 'received content security policy report'); res.status(204); }); } export function csp_headers(res: FastifyReply, server_url: string, policy: string = default_policy) { res.header('Content-Security-Policy', `${policy}; report-uri ${server_url}/.csp-report`); }