import type { FastifyReply, FastifyRequest } from 'fastify'; export interface SecurityHeadersOptions { readonly tls: boolean; } const HSTS_VALUE = 'max-age=31536000'; const CONTENT_SECURITY_POLICY = "default-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; font-src 'self' data:; form-action 'self'; base-uri 'none'; frame-ancestors 'self'"; export function createSecurityHeadersHook( opts: SecurityHeadersOptions, ): (req: FastifyRequest, reply: FastifyReply, payload: unknown) => Promise { return async (_req, reply, payload) => { reply.header('X-Content-Type-Options', 'nosniff'); reply.header('Referrer-Policy', 'no-referrer'); reply.header('Content-Security-Policy', CONTENT_SECURITY_POLICY); if (opts.tls === true) { reply.header('Strict-Transport-Security', HSTS_VALUE); } return payload; }; }