new-site/api/src/middleware/security.ts
justin f8cd37ac8c Initial commit — Performance West telecom compliance platform
Includes: API (Express/TypeScript), Astro site, Python workers,
document generators, FCC compliance tools, Canada CRTC formation,
Ansible infrastructure, and deployment scripts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-27 06:54:22 -05:00

38 lines
1.2 KiB
TypeScript

import helmet from "helmet";
import type { Request, Response, NextFunction } from "express";
// Strict security headers via Helmet.
export const securityHeaders = helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'none'"],
frameAncestors: ["'none'"],
},
},
hsts: { maxAge: 31_536_000, includeSubDomains: true, preload: true },
frameguard: { action: "deny" },
noSniff: true,
referrerPolicy: { policy: "no-referrer" },
hidePoweredBy: true,
// This is a public API accessed cross-origin — must be cross-origin not same-origin
crossOriginResourcePolicy: { policy: "cross-origin" },
// Allow cross-origin opener for Stripe Identity redirect flows
crossOriginOpenerPolicy: { policy: "unsafe-none" },
});
// Attach normalised client IP to req (handles IPv6-mapped IPv4).
declare global {
namespace Express {
interface Request {
clientIp?: string;
}
}
}
export function extractClientIp(req: Request, _res: Response, next: NextFunction): void {
let ip = (req.headers["x-forwarded-for"] as string)?.split(",")[0]?.trim() || req.ip || "";
// Normalise ::ffff:127.0.0.1 → 127.0.0.1
if (ip.startsWith("::ffff:")) ip = ip.slice(7);
req.clientIp = ip;
next();
}