/** * Normalize the CSRF options into a fully-populated config with defaults. */ export function normalizeCsrf(options: any): { secret: any; cookieName: any; headerName: any; formField: any; ignoreMethods: Set; cookieOptions: any; tokenFromRequest: any; }; /** * Normalize the rate-limit options. `limiter` is required. */ export function normalizeRateLimit(options: any): { limiter: any; keyGenerator: any; onDenied: any; trustProxy: boolean; headers: any; }; /** * Normalize the umbrella `securityMiddleware()` options. Returns per-concern * configs (or `null` when disabled) that adapters compose. * * @param {SecurityMiddlewareOptions} options */ export function normalizeUmbrella(options?: SecurityMiddlewareOptions): { responseHeaders: Record | null; corsCheck: ((input: CorsInput) => CorsDecision | Promise) | null; csrf: { secret: any; cookieName: any; headerName: any; formField: any; ignoreMethods: Set; cookieOptions: any; tokenFromRequest: any; } | null; rateLimit: { limiter: any; keyGenerator: any; onDenied: any; trustProxy: boolean; headers: any; } | null; }; export function extractCsrfToken(csrfConfig: any, req: any): any; export function issueCsrfToken(csrfConfig: any): string; export function verifyCsrfPair(csrfConfig: any, cookie: any, headerValue: any): boolean; export function serializeCookie(name: any, value: any, opts: any): string; export function rateLimitDenialBody(result: any): { error: string; message: string; retryAfter: any; }; /** * Apply the response-header map. Returns nothing (never terminates). * * @param {ReadonlyArray<[string, string]>} entries From `Object.entries(buildHeaders(...))`. * @param {AdapterContext} ctx */ export function runHeaders(entries: ReadonlyArray<[string, string]>, ctx: AdapterContext): Promise; /** * @param {ReturnType} corsCheck * @param {AdapterContext} ctx * @param {ReadonlyArray<[string, string]> | null} [staticHeaders] * Response-header map to fold into a preflight response so a preflight * also carries the security headers the caller expects on every reply. * @returns {Promise} Response value (truthy → terminated) or null. */ export function runCors(corsCheck: ReturnType, ctx: AdapterContext, staticHeaders?: ReadonlyArray<[string, string]> | null): Promise; /** * @param {ReturnType} rateLimit * @param {AdapterContext} ctx * @returns {Promise} */ export function runRateLimit(rateLimit: ReturnType, ctx: AdapterContext): Promise; /** * @param {ReturnType} csrf * @param {AdapterContext} ctx * @returns {Promise} */ export function runCsrf(csrf: ReturnType, ctx: AdapterContext): Promise; export const parseCookies: typeof sharedParseCookies; export type AdapterContext = { /** * Uppercased HTTP method. */ method: () => string; /** * Case-insensitive header lookup on the request. */ getHeader: (name: string) => string | undefined; /** * Parsed request cookies. */ cookies: () => Record; /** * Parsed request body (or undefined) — used by the CSRF form-field * fallback when a token isn't in the header. */ body: () => unknown; /** * Overwrite (or first-write) a response header. */ setHeader: (name: string, value: string) => void; /** * Set a response header only if it isn't already present. */ setHeaderIfAbsent: (name: string, value: string) => void; /** * Append a `Set-Cookie` header (or use the framework's native cookie * API where available, e.g. Fastify's `reply.setCookie`). */ setCookie: (cookieName: string, cookieValue: string, cookieOptions: object) => void; /** * Terminal response with a JSON body. Returns whatever the framework * expects the middleware to return (Express/Fastify: undefined). */ json: (status: number, body: unknown, extraHeaders?: Record) => unknown; /** * Terminal response with no body. */ noContent: (status: number, extraHeaders?: Record) => unknown; /** * Best-effort client IP (frameworks resolve this differently). */ ip: () => string | undefined; /** * Escape hatch for user callbacks (`keyGenerator`, `tokenFromRequest`) * that expect the framework-native request object. */ rawReq: () => unknown; /** * Escape hatch for `onDenied`. */ rawRes: () => unknown; /** * Attach state to the request/context for later handlers * (e.g. `req.csrfToken = () => ...`). */ decorate: (key: string, value: unknown) => void; }; export type CsrfMiddlewareOptions = { /** * Minimum 32 bytes of entropy. */ secret: string | Buffer; cookieName?: string | undefined; headerName?: string | undefined; /** * Form body field name. Defaults to * `cookieName`, but overriding lets * you decouple cookie naming from the * `` your templates use. */ formField?: string | undefined; ignoreMethods?: string[] | undefined; /** * Overrides for the Set-Cookie flags. */ cookieOptions?: object | undefined; tokenFromRequest?: ((req: unknown) => string | undefined) | undefined; }; export type RateLimitMiddlewareOptions = { limiter: { check: Function; }; keyGenerator?: ((req: unknown) => string | undefined) | undefined; onDenied?: ((req: unknown, res: unknown, result: object) => unknown) | undefined; /** * Whether the default key generator may read the client IP from the * `X-Forwarded-For` header. That header is client-controlled, so trusting * it without a proxy in front lets an attacker rotate it to mint unlimited * rate-limit buckets (limit bypass) or spoof another user's IP. Leave * `false` unless your app sits behind a proxy/CDN that overwrites XFF. * Ignored when `keyGenerator` is supplied. (Express adapter uses `req.ip`, * which already honours the framework's own `trust proxy` setting.) */ trustProxy?: boolean | undefined; }; export type SecurityMiddlewareOptions = { headers?: boolean | import("../headers/index.js").HeadersOptions | undefined; cors?: false | import("../cors/index.js").CorsOptions | undefined; csrf?: false | CsrfMiddlewareOptions | undefined; rateLimit?: false | RateLimitMiddlewareOptions | undefined; }; export type RateLimitHeaderNames = { /** * Header name for remaining budget. */ remaining?: string | false | undefined; /** * Header name for reset timestamp. */ reset?: string | false | undefined; /** * Header name for the deny hint. */ retryAfter?: string | false | undefined; }; import { cors as buildCorsCheck } from '../cors/index.js'; import { parseCookies as sharedParseCookies } from '@exortek/shared/cookie'; import { headers as buildHeaders } from '../headers/index.js'; export { buildCorsCheck, buildHeaders };