/** * Parse JSON with a prototype-pollution guard. Complements * `freezePrototypes()` — that closes the door on writes to * `Object.prototype` globally; `safeJsonParse` closes the door at the * request boundary where user-controlled JSON enters. * * Returns `null` on any failure (parse error, banned key in `reject` * mode, oversize input) so callers can uniformly branch on `!result`. * * @param {string | Buffer} input * @param {SafeJsonParseOptions} [options] * @returns {unknown | null} */ export function safeJsonParse(input: string | Buffer, options?: SafeJsonParseOptions): unknown | null; /** * Constant-time equality for user-supplied tokens / signatures. * * `node:crypto`'s `timingSafeEqual` throws when lengths differ — which * itself leaks length via the exception path. This wrapper accepts * strings or byte views, returns `false` on length mismatch without * throwing, and burns a fixed amount of comparison time in that path. * * @param {string | Buffer | Uint8Array} a * @param {string | Buffer | Uint8Array} b * @returns {boolean} */ export function constantTimeEqual(a: string | Buffer | Uint8Array, b: string | Buffer | Uint8Array): boolean; /** * @typedef {object} CspReport * @property {string | undefined} documentUri * @property {string | undefined} referrer * @property {string | undefined} blockedUri * @property {string | undefined} effectiveDirective * @property {string | undefined} violatedDirective * @property {string | undefined} disposition 'enforce' | 'report' * @property {number | undefined} statusCode * @property {string | undefined} sourceFile * @property {number | undefined} lineNumber * @property {number | undefined} columnNumber * @property {string | undefined} sample * @property {string | undefined} originalPolicy */ /** * Normalize a CSP violation report submitted to a `report-uri` or * `report-to` endpoint into a flat object. Browsers ship two dialects: * * 1. Legacy `report-uri` (Content-Type: application/csp-report) * `{ "csp-report": { "blocked-uri": "...", ... } }` * 2. Modern `report-to` (Content-Type: application/reports+json) * `[ { "type": "csp-violation", "body": { "blockedURL": "...", ... } } ]` * * Both use kebab / snake / camelCase inconsistently across engines. * This helper takes the raw body (string OR already-parsed object) and * returns a single normalized shape. Returns `null` when the body is * not a recognizable CSP report. * * @param {unknown} body * @returns {CspReport | null} */ export function parseCspReport(body: unknown): CspReport | null; export type CspReport = { documentUri: string | undefined; referrer: string | undefined; blockedUri: string | undefined; effectiveDirective: string | undefined; violatedDirective: string | undefined; /** * 'enforce' | 'report' */ disposition: string | undefined; statusCode: number | undefined; sourceFile: string | undefined; lineNumber: number | undefined; columnNumber: number | undefined; sample: string | undefined; originalPolicy: string | undefined; }; export type SafeJsonParseOptions = { /** * How to react to `__proto__` / `constructor` / `prototype` keys. * - `reject` (default): return `null`, the parsed result is discarded. * - `strip`: silently drop the offending keys, keep the rest. * - `throw`: raise `SecurityError` — surface bad payloads loudly. */ mode?: "strip" | "reject" | "throw" | undefined; /** * Refuses to walk beyond this level. Guards against pathological / * self-referential payloads that could stall the event loop. */ maxDepth?: number | undefined; /** * Reject the input outright when longer than this. Comes before the * parse, so we never actually construct a huge object graph. */ maxBytes?: number | undefined; /** * Keys that are considered dangerous. Defaults cover the classic * prototype-pollution vectors; extend if your app has extra concerns. */ banned?: Set | undefined; };