mitigator 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/sanitize/index.ts","../src/headers/index.ts","../src/auth/index.ts","../src/crypto/index.ts","../src/utils/telemetry.ts","../src/fs/index.ts","../src/http/index.ts","../src/rate-limit/index.ts","../src/safe-json/index.ts","../src/safe-merge/index.ts","../src/utils/index.ts","../src/utils/presets.ts"],"sourcesContent":["/**\n * Basic HTML escaping for common characters.\n */\nexport const escapeHtml = (input: string): string => {\n const map: Record<string, string> = {\n '&': '&amp;',\n '<': '&lt;',\n '>': '&gt;',\n '\"': '&quot;',\n \"'\": '&#39;',\n };\n return input.replaceAll(/[&<>\"']/g, (m) => map[m]!);\n};\n\n/**\n * Strips all HTML tags from a string.\n */\nexport const stripTags = (input: string): string => {\n return input.replaceAll(/<[^>]*>?/gm, '');\n};\n\nimport sanitizeHtmlLib from 'sanitize-html';\n\n/**\n * Standard allowlist for \"clean\" HTML sanitization.\n */\nexport const ALLOWLIST: Record<string, string[]> = {\n b: [],\n i: [],\n em: [],\n strong: [],\n p: ['style'],\n a: ['href', 'title', 'target'],\n ul: [],\n ol: [],\n li: [],\n br: [],\n span: ['style'],\n};\n\n/**\n * Robust HTML sanitizer.\n * Uses the industry-standard `sanitize-html` library.\n */\nexport const sanitizeHtml = (html: string, rules: Record<string, string[]> = ALLOWLIST): string => {\n return sanitizeHtmlLib(html, {\n allowedTags: Object.keys(rules),\n allowedAttributes: rules,\n allowedSchemes: ['http', 'https', 'mailto', 'tel'],\n allowProtocolRelative: false,\n enforceHtmlBoundary: true,\n });\n};\n\n/**\n * Defensive post-processor that namespaces 'id' and 'name' attributes to prevent DOM Clobbering attacks.\n * Attackers use clobbering to overwrite global variables (window.foo) by naming an element 'id=foo'.\n *\n * @param html The HTML string to process.\n * @param prefix The unique namespace prefix (default: sk-).\n */\nexport const preventDOMClobbering = (html: string, prefix: string = 'sk-'): string => {\n const attrRegex = /(\\s(id|name)\\s*=\\s*)(?:\"([^\"]*)\"|'([^']*)'|([^\\s>]+))/gi;\n\n return html.replaceAll(attrRegex, (_match, attrPrefix, _attrName, val1, val2, val3) => {\n const value = val1 || val2 || val3;\n\n let quote: string;\n if (val3) {\n quote = '';\n } else if (val1) {\n quote = '\"';\n } else {\n quote = \"'\";\n }\n\n return `${attrPrefix}${quote}${prefix}${value}${quote}`;\n });\n};\n\n/**\n * Basic SVG & MathML sanitization.\n */\nexport const sanitizeMediaTags = (html: string): string => {\n const dangerousTags = [\n 'script',\n 'animate',\n 'set',\n 'animateMotion',\n 'animateTransform',\n 'handler',\n 'discard',\n 'foreignObject',\n ];\n let result = html;\n dangerousTags.forEach((tag) => {\n const regex = new RegExp(String.raw`<${tag}[^>]*>[\\s\\S]*?<\\/${tag}>|<${tag}[^>]*\\/>`, 'gi');\n result = result.replaceAll(regex, '');\n });\n return result;\n};\n\n/**\n * Validates if a string is a safe URL.\n */\nexport const isSafeUrl = (url: string): boolean => {\n const allowedProtocols = ['https:', 'http:', 'mailto:', 'tel:'];\n try {\n const parsed = new URL(url);\n return allowedProtocols.includes(parsed.protocol);\n } catch {\n const low = url.trim().toLowerCase();\n return (\n !low.startsWith('javascript:') &&\n !low.startsWith('//') &&\n (low.startsWith('/') || low.startsWith('.'))\n );\n }\n};\n","import { randomBytes } from 'node:crypto';\n\n/**\n * Standard security header presets.\n */\nexport const standardHeaders = {\n 'Content-Security-Policy':\n \"default-src 'self'; img-src 'self'; script-src 'self'; style-src 'self'; frame-ancestors 'none'; object-src 'none'\",\n 'X-Frame-Options': 'DENY',\n 'X-Content-Type-Options': 'nosniff',\n 'Referrer-Policy': 'strict-origin-when-cross-origin',\n 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains',\n};\n\n/**\n * CSP Directive Map type.\n */\nexport type CSPDirectives = {\n 'default-src'?: string[];\n 'script-src'?: string[];\n 'style-src'?: string[];\n 'img-src'?: string[];\n 'connect-src'?: string[];\n 'font-src'?: string[];\n 'object-src'?: string[];\n 'media-src'?: string[];\n 'frame-src'?: string[];\n sandbox?: string[];\n 'report-uri'?: string[];\n 'child-src'?: string[];\n 'form-action'?: string[];\n 'frame-ancestors'?: string[];\n 'plugin-types'?: string[];\n 'base-uri'?: string[];\n 'report-to'?: string[];\n 'worker-src'?: string[];\n 'manifest-src'?: string[];\n 'prefetch-src'?: string[];\n 'navigate-to'?: string[];\n};\n\n/**\n * Generates a random nonce for CSP headers.\n */\nexport const generateNonce = (length: number = 16): string => {\n return randomBytes(length).toString('base64');\n};\n\n/**\n * Builds a CSP string.\n */\nexport const buildCSP = (directives: CSPDirectives, nonce?: string): string => {\n return Object.entries(directives)\n .filter((entry): entry is [string, string[]] => {\n const sources = entry[1];\n return Array.isArray(sources) && sources.length > 0;\n })\n .map(([directive, sources]) => {\n const updatedSources =\n nonce && (directive === 'script-src' || directive === 'style-src')\n ? [...sources, `'nonce-${nonce}'`]\n : sources;\n return `${directive} ${updatedSources.join(' ')}`;\n })\n .join('; ');\n};\n\n/**\n * Builds a 'Strict CSP' which is the industry gold standard.\n * It uses 'strict-dynamic' and nonces, rendering 99.9% of XSS impossible.\n *\n * @param nonce The nonce generated for the current request.\n * @returns {string} The formatted Strict CSP string.\n */\nexport const buildStrictCSP = (nonce: string): string => {\n return buildCSP(\n {\n 'object-src': [\"'none'\"],\n 'script-src': [\"'strict-dynamic'\", `'nonce-${nonce}'`, \"'unsafe-inline'\", 'http:', 'https:'],\n 'base-uri': [\"'none'\"],\n },\n nonce,\n );\n};\n\n/**\n * Parses CSP violation report.\n */\nexport const parseCSPReport = (reportBody: any) => {\n if (!reportBody) return null;\n const report =\n reportBody['csp-report'] || (Array.isArray(reportBody) ? reportBody[0] : reportBody);\n if (!report?.['blocked-uri']) return null;\n return {\n documentUri: report['document-uri'],\n referrer: report['referrer'],\n blockedUri: report['blocked-uri'],\n violatedDirective: report['violated-directive'],\n originalPolicy: report['original-policy'],\n disposition: report['disposition'],\n statusCode: report['status-code'],\n timestamp: new Date().toISOString(),\n };\n};\n\n/**\n * Returns a secure-by-default CSP string.\n */\nexport const secureCSP = buildCSP({\n 'default-src': [\"'none'\"],\n 'script-src': [\"'self'\"],\n 'style-src': [\"'self'\"],\n 'img-src': [\"'self'\"],\n 'connect-src': [\"'self'\"],\n 'font-src': [\"'self'\"],\n 'object-src': [\"'none'\"],\n 'base-uri': [\"'none'\"],\n 'form-action': [\"'self'\"],\n 'frame-ancestors': [\"'none'\"],\n});\n","import { Buffer } from 'node:buffer';\nimport { randomBytes, timingSafeEqual, createHmac, createHash, verify } from 'node:crypto';\n\n/**\n * Basic authentication helper.\n */\nexport const basicAuth = (user: string, pass: string): string => {\n const credentials = user + ':' + pass;\n return 'Basic ' + Buffer.from(credentials).toString('base64');\n};\n\n/**\n * Passkey / WebAuthn Core Helper to verify an authentication signature.\n * Supports industry-standard RS256 and ES256 algorithms.\n *\n * @param challenge The challenge originally sent to the client.\n * @param response Authenticatable data from the client (authenticatorData + clientDataJSON).\n * @param signature The cryptographic signature from the WebAuthn response.\n * @param publicKey The credential's public key (PEM format).\n */\nexport const verifyPasskeySignature = (\n _challenge: string | Buffer,\n response: string | Buffer,\n signature: string | Buffer,\n publicKey: string,\n algorithm: 'sha256' | 'sha512' = 'sha256',\n): boolean => {\n try {\n const data = Buffer.isBuffer(response) ? response : Buffer.from(response);\n const sig = Buffer.isBuffer(signature) ? signature : Buffer.from(signature, 'base64');\n\n return verify(algorithm, data, publicKey, sig);\n } catch {\n return false;\n }\n};\n\n/**\n * Heuristic Auth Advisor.\n */\nexport const suggestMFA = (\n riskScore: number,\n lastFingerprint: string,\n currentFingerprint: string,\n): boolean => {\n if (lastFingerprint !== currentFingerprint) return true;\n if (riskScore > 10) return true;\n return false;\n};\n\n/**\n * Generates a random HMAC-based challenge for a challenge-response authentication flow.\n *\n * The server generates a per-request challenge that is tied to a user-specific salt.\n * The client proves knowledge of a shared secret by computing HMAC(challenge, secret)\n * and returning the result. The server verifies it with `verifyHmacResponse`.\n *\n * Note: This is an HMAC challenge-response protocol, not a zero-knowledge proof (ZKP).\n * A true ZKP would allow the client to prove knowledge of the secret without revealing\n * it even to a compromised verifier. Use this for server-side mutual authentication only.\n *\n * @param userSalt - A per-user, per-session random salt to bind the challenge.\n */\nexport const generateHmacChallenge = (userSalt: string): string => {\n return createHmac('sha256', userSalt).update(randomBytes(32)).digest('hex');\n};\n\n/**\n * Verifies an HMAC challenge-response: checks that `proof === HMAC(challenge, secret)`\n * using a timing-safe comparison to prevent timing attacks.\n *\n * @param challenge - The challenge string previously returned by `generateHmacChallenge`.\n * @param proof - The response computed by the client: `HMAC-SHA256(secret, challenge)`.\n * @param secret - The shared secret known to the server.\n */\nexport const verifyHmacResponse = (challenge: string, proof: string, secret: string): boolean => {\n const expected = createHmac('sha256', secret).update(challenge).digest('hex');\n const proofBuf = Buffer.from(proof, 'hex');\n const expectedBuf = Buffer.from(expected, 'hex');\n if (proofBuf.length !== expectedBuf.length) return false;\n return timingSafeEqual(proofBuf, expectedBuf);\n};\n\n/**\n * Honey-Token generation.\n */\nexport const generateHoneyToken = (prefix: string = 'sk'): string => {\n return `${prefix}_${randomBytes(16).toString('hex')}_${randomBytes(8).toString('hex')}`;\n};\n\nexport const isHoneyToken = (token: string, prefix: string = 'sk'): boolean => {\n if (!token) return false;\n const parts = token.split('_');\n return parts.length >= 3 && parts[0] === prefix;\n};\n\n/**\n * CSRF management.\n */\nexport const generateCSRF = () => {\n const token = randomBytes(32).toString('hex');\n const cookieValue = randomBytes(32).toString('hex');\n return { token, cookieValue };\n};\n\nexport const verifyCSRF = (providedToken: string, cookieToken: string): boolean => {\n if (!providedToken || !cookieToken) return false;\n const tokenBuf = Buffer.from(providedToken, 'hex');\n const cookieBuf = Buffer.from(cookieToken, 'hex');\n if (tokenBuf.length !== cookieBuf.length) return false;\n return timingSafeEqual(tokenBuf, cookieBuf);\n};\n\n/**\n * JWT Validation.\n * Verifies the structure, expiration, and cryptographic signature of the token.\n *\n * @param token The JWT string.\n * @param secretOrPublicKey The secret (for HS256) or public key (for RS256) to verify the signature.\n * @param algorithm Optional. The expected algorithm (e.g., 'HS256', 'RS256'). Defaults to 'HS256'.\n */\nexport const isJwtValid = (\n token: string,\n secretOrPublicKey: string | Buffer,\n algorithm: string = 'HS256',\n): boolean => {\n try {\n const parts = token.split('.');\n if (parts.length !== 3) return false;\n\n const [headerB64, payloadB64, signatureB64] = parts;\n\n const header = JSON.parse(Buffer.from(headerB64, 'base64url').toString('utf8'));\n if (!header.alg || header.alg.toLowerCase() === 'none' || header.alg !== algorithm)\n return false;\n\n const payload = JSON.parse(Buffer.from(payloadB64, 'base64url').toString('utf8'));\n if (payload.exp && Date.now() >= payload.exp * 1000) return false;\n\n // Verify signature\n const dataToSign = `${headerB64}.${payloadB64}`;\n const signatureBuffer = Buffer.from(signatureB64, 'base64url');\n\n if (algorithm.startsWith('HS')) {\n const hashAlg = algorithm.replace('HS', 'sha');\n const expectedSignature = createHmac(hashAlg, secretOrPublicKey).update(dataToSign).digest();\n if (signatureBuffer.length !== expectedSignature.length) return false;\n return timingSafeEqual(signatureBuffer, expectedSignature);\n } else if (algorithm.startsWith('RS') || algorithm.startsWith('ES')) {\n const hashAlg = algorithm.replace(/RS|ES/, 'sha');\n return verify(hashAlg, Buffer.from(dataToSign), secretOrPublicKey, signatureBuffer);\n }\n\n return false;\n } catch {\n return false;\n }\n};\n\n/**\n * Auth guards.\n */\nexport const canAccess = <U, R>(user: U, resource: R, rule: (u: U, r: R) => boolean): boolean => {\n return rule(user, resource);\n};\n\nexport const hasRole = (userRoles: string[], requiredRoles: string[]): boolean => {\n return requiredRoles.every((role) => userRoles.includes(role));\n};\n\nexport const can = (userPermissions: string[], requiredPermission: string): boolean => {\n return userPermissions.includes(requiredPermission);\n};\n\n/**\n * Generates a random base64url challenge for FIDO2 WebAuthn / Passkeys.\n */\nexport const generatePasskeyChallenge = (length: number = 32): string => {\n return randomBytes(length).toString('base64url');\n};\n\n/**\n * Interface representing the unpacked and verified result of a Passkey registration.\n */\nexport interface PasskeyRegistrationResult {\n verified: boolean;\n error?: string;\n}\n\n/**\n * Validates a Passkey registration response against the expected challenge and origin.\n *\n * Accepts `clientDataJSONStr` as either:\n * - A raw UTF-8 JSON string (for testing/server-side construction)\n * - A base64url-encoded JSON string (as browsers send in `response.clientDataJSON`)\n *\n * The challenge is compared at the byte level using `timingSafeEqual` after\n * decoding both sides from base64url, per the WebAuthn Level 2 spec §7.1.\n */\nexport const verifyPasskeyRegistration = (\n clientDataJSONStr: string,\n expectedChallenge: string,\n expectedOrigin?: string,\n): PasskeyRegistrationResult => {\n try {\n // Resolve the raw JSON: try direct parse first (raw JSON string),\n // then fall back to base64url decode (browser-sent format).\n let jsonStr = clientDataJSONStr;\n try {\n JSON.parse(clientDataJSONStr);\n } catch {\n // Not raw JSON — treat as base64url-encoded clientDataJSON (browser format)\n jsonStr = Buffer.from(clientDataJSONStr, 'base64url').toString('utf8');\n }\n\n const clientData = JSON.parse(jsonStr);\n\n // WebAuthn spec §7.1 step 11: compare challenge bytes, not strings.\n // Both clientData.challenge and expectedChallenge are base64url strings;\n // decode to bytes and use timingSafeEqual to prevent timing attacks and\n // tolerate any base64url padding variation.\n const receivedBytes = Buffer.from(clientData.challenge ?? '', 'base64url');\n const expectedBytes = Buffer.from(expectedChallenge, 'base64url');\n const challengeMatches =\n receivedBytes.length === expectedBytes.length &&\n receivedBytes.length > 0 &&\n timingSafeEqual(receivedBytes, expectedBytes);\n\n const typeMatches = clientData.type === 'webauthn.create';\n\n let originMatches = true;\n if (expectedOrigin && clientData.origin !== expectedOrigin) {\n originMatches = false;\n }\n\n if (!challengeMatches) return { verified: false, error: 'Challenge mismatch.' };\n if (!typeMatches) return { verified: false, error: 'Invalid type (expected webauthn.create).' };\n if (!originMatches) return { verified: false, error: 'Origin mismatch.' };\n\n return { verified: true };\n } catch (err: any) {\n return { verified: false, error: err.message };\n }\n};\n\n/**\n * Parses WebAuthn raw authenticator data (authData) buffer to extract the\n * aaguid, credential ID, and public key bytes according to the FIDO2 spec.\n */\nexport const parseAuthenticatorData = (authData: Buffer) => {\n try {\n const rpIdHash = authData.subarray(0, 32);\n const flags = authData[32];\n const signCount = authData.readUInt32BE(33);\n\n // Bit 6 of flags indicates if attestedCredentialData is present\n const attestedCredentialDataPresent = !!(flags & 0x40);\n\n if (!attestedCredentialDataPresent) {\n return { rpIdHash, flags, signCount };\n }\n\n const aaguid = authData.subarray(37, 53);\n const credentialIdLength = authData.readUInt16BE(53);\n const credentialId = authData.subarray(55, 55 + credentialIdLength);\n const publicKeyBytes = authData.subarray(55 + credentialIdLength);\n\n return {\n rpIdHash,\n flags,\n signCount,\n aaguid,\n credentialId: credentialId.toString('base64url'),\n publicKeyBytes: publicKeyBytes.toString('hex'),\n };\n } catch {\n return null;\n }\n};\n\n/**\n * Result returned by `verifyPasskeyAssertion`.\n */\nexport interface PasskeyAssertionResult {\n /** Whether the assertion passed all WebAuthn §7.2 checks. */\n verified: boolean;\n /**\n * The new signature counter value from the authenticator.\n * Persist this value and pass it as `storedSignCount` on the next assertion to\n * detect cloned authenticators (replay attack protection).\n */\n newSignCount?: number;\n /** Human-readable error message when `verified` is false. */\n error?: string;\n}\n\n/**\n * Verifies a FIDO2 WebAuthn assertion response (navigator.credentials.get flow).\n *\n * Implements WebAuthn Level 2 §7.2 — Verifying an Authentication Assertion.\n *\n * Checks performed (in order):\n * 1. Parses `clientDataJSON` — accepts both raw JSON and browser base64url-encoded format.\n * 2. Verifies `type === 'webauthn.get'`.\n * 3. Verifies the challenge at the byte level using `timingSafeEqual` (prevents timing attacks).\n * 4. Verifies the origin.\n * 5. Verifies `signCount > storedSignCount` (replay / cloned-authenticator detection).\n * 6. Verifies the cryptographic signature over `authData || SHA-256(clientDataJSON)`\n * using the stored public key.\n *\n * @param clientDataJSONStr - The `response.clientDataJSON` from the browser, as either a\n * raw UTF-8 JSON string or a base64url-encoded string (browser format).\n * @param expectedChallenge - The base64url-encoded challenge originally sent to the client.\n * @param expectedOrigin - The expected origin (e.g. `'https://example.com'`).\n * @param storedSignCount - The sign count stored server-side from the last successful assertion.\n * Pass `0` for the first assertion after registration.\n * @param authData - The raw `response.authenticatorData` buffer from the browser.\n * @param signature - The raw `response.signature` buffer from the browser.\n * @param publicKeyPem - The credential's stored public key in PEM (SPKI) format.\n *\n * @example\n * const result = verifyPasskeyAssertion(\n * clientDataJSON, // from navigator.credentials.get() response\n * storedChallenge,\n * 'https://example.com',\n * storedSignCount,\n * authDataBuffer,\n * signatureBuffer,\n * credentialPublicKeyPem,\n * );\n * if (!result.verified) throw new Error(result.error);\n * await db.updateSignCount(credentialId, result.newSignCount!);\n */\nexport const verifyPasskeyAssertion = (\n clientDataJSONStr: string,\n expectedChallenge: string,\n expectedOrigin: string,\n storedSignCount: number,\n authData: Buffer,\n signature: Buffer,\n publicKeyPem: string,\n): PasskeyAssertionResult => {\n try {\n // Step 1: Resolve raw JSON — same dual-format handling as verifyPasskeyRegistration\n let jsonStr = clientDataJSONStr;\n try {\n JSON.parse(clientDataJSONStr);\n } catch {\n // Not raw JSON — treat as base64url-encoded clientDataJSON (browser format)\n jsonStr = Buffer.from(clientDataJSONStr, 'base64url').toString('utf8');\n }\n\n const clientData = JSON.parse(jsonStr);\n\n // Step 2: type must be 'webauthn.get'\n if (clientData.type !== 'webauthn.get') {\n return { verified: false, error: 'Invalid type (expected webauthn.get).' };\n }\n\n // Step 3: Compare challenge bytes via timingSafeEqual (§7.2 step 11)\n const receivedBytes = Buffer.from(clientData.challenge ?? '', 'base64url');\n const expectedBytes = Buffer.from(expectedChallenge, 'base64url');\n const challengeMatches =\n receivedBytes.length === expectedBytes.length &&\n receivedBytes.length > 0 &&\n timingSafeEqual(receivedBytes, expectedBytes);\n\n if (!challengeMatches) return { verified: false, error: 'Challenge mismatch.' };\n\n // Step 4: Verify origin\n if (clientData.origin !== expectedOrigin) {\n return { verified: false, error: 'Origin mismatch.' };\n }\n\n // Step 5: Sign count — must be strictly greater to detect cloned authenticators.\n // Per §7.2 step 17: if storedSignCount is 0 (counter not supported), skip check.\n const newSignCount: number = authData.readUInt32BE(33);\n if (storedSignCount !== 0 && newSignCount <= storedSignCount) {\n return {\n verified: false,\n error: `Replay attack or cloned authenticator detected: signCount ${newSignCount} is not greater than stored ${storedSignCount}.`,\n };\n }\n\n // Step 6: Verify signature over authData || SHA-256(clientDataJSON)\n // The signed data is: authData || hash(clientDataJSON bytes) per §7.2 step 19\n const clientDataHash = createHash('sha256').update(Buffer.from(jsonStr, 'utf8')).digest();\n const signedData = Buffer.concat([authData, clientDataHash]);\n\n const sigValid = verify('sha256', signedData, publicKeyPem, signature);\n if (!sigValid) return { verified: false, error: 'Signature verification failed.' };\n\n return { verified: true, newSignCount };\n } catch (err: any) {\n return { verified: false, error: err.message };\n }\n};\n","import { Buffer } from 'node:buffer';\nimport {\n randomBytes,\n createHash,\n scrypt,\n timingSafeEqual,\n createHmac,\n createCipheriv,\n createDecipheriv,\n hkdfSync,\n} from 'node:crypto';\nimport { promisify } from 'node:util';\nimport { fileURLToPath } from 'node:url';\nimport { cpus } from 'node:os';\nimport { getTelemetryProvider } from '../utils/telemetry.js';\n\nconst scryptAsync = promisify(scrypt);\n\n// Dynamically construct filename for pure ES module runtime compatibility\nconst getFilename = (): string => {\n return fileURLToPath(import.meta.url);\n};\n\n/**\n * Bounded semaphore that caps the number of concurrently running Worker Threads.\n *\n * Without this guard, `runIsolatedCrypto` would spawn a new OS thread for every\n * call, allowing a high-concurrency burst to exhaust system resources (DoS).\n * Tasks that arrive when the pool is full are queued and drained FIFO as slots free.\n *\n * Default concurrency: `max(2, cpus - 1)` — leaves one core for the event loop.\n */\nclass BoundedWorkerSemaphore {\n private active = 0;\n private readonly queue: Array<() => void> = [];\n\n constructor(private readonly maxConcurrent: number = Math.max(2, cpus().length - 1)) {}\n\n async run<T>(task: () => Promise<T>): Promise<T> {\n if (this.active >= this.maxConcurrent) {\n // Park the caller until a slot is freed\n await new Promise<void>((resolve) => this.queue.push(resolve));\n }\n this.active++;\n try {\n return await task();\n } finally {\n this.active--;\n // Drain the next queued caller if one is waiting\n const next = this.queue.shift();\n if (next) next();\n }\n }\n}\n\n/** Module-level singleton — shared across all runIsolatedCrypto calls. */\nconst workerPool = new BoundedWorkerSemaphore();\n\n/**\n * Runs a high-CPU cryptographic function in a separate Worker Thread.\n * Concurrency is bounded by the module-level `workerPool` semaphore, preventing\n * unbounded thread allocation under high load.\n *\n * Note: Workers are still spawned on-demand (not persistent). For extremely\n * high-throughput workloads consider replacing this with a persistent pool\n * library such as Piscina.\n */\nexport const runIsolatedCrypto = async (functionName: string, args: any[]): Promise<any> => {\n return workerPool.run(async () => {\n getTelemetryProvider().onWorkerSpawned?.(functionName);\n const { Worker } = await import('node:worker_threads');\n return new Promise((resolve, reject) => {\n const worker = new Worker(getFilename(), {\n workerData: { functionName, args },\n });\n worker.on('message', (msg) => {\n if (msg && msg.status === 'success') {\n resolve(msg.result !== undefined ? msg.result : msg);\n } else {\n reject(new Error(msg?.error || 'Worker execution failed.'));\n }\n });\n worker.on('error', reject);\n worker.on('exit', (code) => {\n if (code !== 0) reject(new Error(`Worker stopped with exit code ${code}`));\n });\n });\n });\n};\n\n// Galois Field 256 Log/Exp tables for polynomial math in Shamir's Secret Sharing\nconst gfExp = new Uint8Array(256);\nconst gfLog = new Uint8Array(256);\nlet gfX = 1;\nfor (let i = 0; i < 255; i++) {\n gfExp[i] = gfX;\n gfLog[gfX] = i;\n gfX = gfX << 1;\n if (gfX & 0x100) {\n gfX = gfX ^ 0x11d; // standard AES primitive polynomial: x^8 + x^4 + x^3 + x^2 + 1\n }\n}\ngfExp[255] = gfExp[0];\n\nconst gfMul = (a: number, b: number): number => {\n if (a === 0 || b === 0) return 0;\n return gfExp[(gfLog[a] + gfLog[b]) % 255];\n};\n\nconst gfDiv = (a: number, b: number): number => {\n if (a === 0) return 0;\n if (b === 0) throw new Error('Division by zero in GF(256)');\n return gfExp[(gfLog[a] - gfLog[b] + 255) % 255];\n};\n\nconst evaluatePolynomial = (coefficients: number[], x: number): number => {\n let result = 0;\n let power = 1;\n for (const coeff of coefficients) {\n result ^= gfMul(coeff, power);\n power = gfMul(power, x);\n }\n return result;\n};\n\n/**\n * Implements a production-grade verifiable Shamir's Secret Sharing (SSS) pattern to split\n * a master secret into multiple 'shares'. N-of-M shares are required to reconstruct.\n * This provides Threshold Security.\n *\n * @param secret The master secret string or buffer.\n * @param sharesCount Global number of shares (M).\n * @param threshold Minimum number of shares required to reconstruct (N).\n */\nexport const splitSecret = (\n secret: string | Buffer,\n sharesCount: number,\n threshold: number,\n): string[] => {\n if (threshold > sharesCount) throw new Error('Threshold cannot be greater than sharesCount.');\n if (threshold < 1) throw new Error('Threshold must be at least 1.');\n if (sharesCount > 255)\n throw new Error('Shamir Secret Sharing GF(256) supports up to 255 shares.');\n\n const secretBuffer = Buffer.isBuffer(secret) ? secret : Buffer.from(secret);\n\n const secretLen = secretBuffer.length;\n const shareBuffers = Array.from({ length: sharesCount }, () => Buffer.alloc(secretLen));\n\n for (let byteIdx = 0; byteIdx < secretLen; byteIdx++) {\n const s = secretBuffer[byteIdx];\n const coefficients = [s];\n for (let k = 1; k < threshold; k++) {\n coefficients.push(randomBytes(1)[0]);\n }\n\n // Evaluate for each share at x = i + 1 (since x = 0 gives the secret itself)\n for (let i = 0; i < sharesCount; i++) {\n shareBuffers[i][byteIdx] = evaluatePolynomial(coefficients, i + 1);\n }\n }\n\n return shareBuffers.map((buf, i) => `${i + 1}:${buf.toString('hex')}`);\n};\n\n/**\n * Reconstructs a master secret from N-of-M Shamir's Secret Sharing shares.\n *\n * @param shares Array of hex-encoded shares formatted as 'x:hex_payload'.\n */\nexport const reconstructSecret = (shares: string[]): Buffer => {\n if (shares.length === 0) throw new Error('No shares provided.');\n\n const parsedShares = shares.map((s) => {\n const [xStr, hex] = s.split(':');\n return {\n x: Number.parseInt(xStr, 10),\n y: Buffer.from(hex, 'hex'),\n };\n });\n\n const secretLen = parsedShares[0].y.length;\n const secretBuffer = Buffer.alloc(secretLen);\n\n for (let byteIdx = 0; byteIdx < secretLen; byteIdx++) {\n let secretByte = 0;\n for (let i = 0; i < parsedShares.length; i++) {\n let li = 1;\n for (let j = 0; j < parsedShares.length; j++) {\n if (i === j) continue;\n const num = parsedShares[j].x;\n const denom = parsedShares[i].x ^ parsedShares[j].x;\n li = gfMul(li, gfDiv(num, denom));\n }\n secretByte = secretByte ^ gfMul(parsedShares[i].y[byteIdx], li);\n }\n secretBuffer[byteIdx] = secretByte;\n }\n\n return secretBuffer;\n};\n\n/**\n * Blind Signature Framework placeholder.\n * Allows a client to 'blind' a piece of data before sending it for signing.\n */\nexport const blindData = (data: string | Buffer, factor: string): string => {\n return createHmac('sha256', factor).update(data).digest('hex');\n};\n\n/**\n * Generates a random token.\n */\nexport const generateToken = (length: number = 32, encoding: BufferEncoding = 'hex'): string => {\n return randomBytes(length).toString(encoding);\n};\n\n/**\n * HKDF key derivation using the standard HKDF-SHA-256 algorithm (RFC 5869).\n *\n * Derives a cryptographically strong sub-key from a master secret using\n * HKDF-SHA-256 (extract + expand). Safe to use for key diversification,\n * e.g. deriving encryption and MAC keys from a single master secret.\n *\n * @param secret - The input key material (IKM). A high-entropy master secret.\n * @param info - Context/application-specific info string (e.g. 'session-key').\n * Different values produce independent, unrelated sub-keys.\n * @param length - Length of the derived key in bytes (default: 32).\n * @returns Hex-encoded derived key.\n */\nexport const deriveSubKey = (\n secret: string | Buffer,\n info: string,\n length: number = 32,\n): string => {\n const ikm = Buffer.isBuffer(secret) ? secret : Buffer.from(secret);\n // hkdfSync(digest, ikm, salt, info, keylen) — empty salt uses a zero-filled buffer per RFC 5869 §2.2\n const derived = hkdfSync('sha256', ikm, Buffer.alloc(0), Buffer.from(info), length);\n return Buffer.from(derived).toString('hex');\n};\n\n/**\n * AES-256-GCM encrypted persistence.\n */\nexport const encryptSession = (obj: any, key: string | Buffer): string => {\n const iv = randomBytes(12);\n const keyBuffer = Buffer.isBuffer(key) ? key : Buffer.from(key, 'hex');\n const cipher = createCipheriv('aes-256-gcm', keyBuffer, iv);\n const content = JSON.stringify(obj);\n let encrypted = cipher.update(content, 'utf8', 'hex');\n encrypted += cipher.final('hex');\n const authTag = cipher.getAuthTag().toString('hex');\n return `${iv.toString('hex')}:${authTag}:${encrypted}`;\n};\n\n/**\n * Decrypts AES-256-GCM.\n */\nexport const decryptSession = (sessionStr: string, key: string | Buffer): any => {\n try {\n const [ivHex, authTagHex, encrypted] = sessionStr.split(':');\n const keyBuffer = Buffer.isBuffer(key) ? key : Buffer.from(key, 'hex');\n const iv = Buffer.from(ivHex, 'hex');\n const authTag = Buffer.from(authTagHex, 'hex');\n const decipher = createDecipheriv('aes-256-gcm', keyBuffer, iv);\n decipher.setAuthTag(authTag);\n let decrypted = decipher.update(encrypted, 'hex', 'utf8');\n decrypted += decipher.final('utf8');\n return JSON.parse(decrypted);\n } catch {\n return null;\n }\n};\n\nconst WOTS_LEN = 67; // 64 message nibbles + 3 checksum nibbles\n\n/**\n * Module-level registry of public key fingerprints that have already been used to sign.\n *\n * WOTS is a **one-time** signature scheme: signing with the same private key twice\n * leaks enough private key material to forge arbitrary signatures. This registry\n * enforces the one-time constraint at runtime by throwing on key reuse.\n *\n * Note: This registry is in-process only. For multi-process or persistent deployments,\n * enforce key-use tracking in a shared store (e.g. a database) and generate a fresh\n * key pair per message.\n */\nconst _usedWotsKeys = new Set<string>();\n\n/**\n * Generates a Winternitz One-Time Signature (WOTS) key pair for post-quantum signing.\n *\n * @returns An object with `publicKey` and `privateKey` as semicolon-delimited hex strings.\n *\n * @example\n * const { publicKey, privateKey } = generatePQCKeyPair();\n * const signature = signPQC('my message', privateKey);\n * const valid = verifyPQCSignature('my message', signature, publicKey); // true\n *\n * @caution **ONE-TIME USE ONLY.**\n * WOTS is a one-time signature scheme. Each `privateKey` **must only be used to sign\n * a single message**. Signing a second message with the same key reveals partial private\n * key material, completely breaking the security of the scheme. Always generate a new\n * key pair for each message you need to sign.\n */\nexport const generatePQCKeyPair = (): { publicKey: string; privateKey: string } => {\n const privKeyParts: string[] = [];\n const pubKeyParts: string[] = [];\n for (let i = 0; i < WOTS_LEN; i++) {\n const part = randomBytes(32).toString('hex');\n privKeyParts.push(part);\n\n let current = Buffer.from(part, 'hex');\n for (let j = 0; j < 15; j++) {\n current = createHash('sha256').update(current).digest();\n }\n pubKeyParts.push(current.toString('hex'));\n }\n return {\n publicKey: pubKeyParts.join(';'),\n privateKey: privKeyParts.join(';'),\n };\n};\n\n/**\n * Signs a message using a Winternitz One-Time Signature (WOTS) private key.\n *\n * @param data - The message or data to sign.\n * @param privateKeyStr - The private key string returned by `generatePQCKeyPair`.\n *\n * @throws {Error} If `privateKeyStr` is invalid (wrong number of key parts).\n * @throws {Error} If this private key has already been used to sign a message\n * (`WOTS_KEY_REUSE`). Generate a fresh key pair for each message.\n *\n * @caution **ONE-TIME USE ONLY.** See `generatePQCKeyPair` for the full warning.\n */\nexport const signPQC = (data: string | Buffer, privateKeyStr: string): string => {\n const msgHash = createHash('sha256').update(data).digest();\n const nibbles: number[] = [];\n let checksum = 0;\n for (let i = 0; i < 32; i++) {\n const byte = msgHash[i];\n const n1 = byte >> 4;\n const n2 = byte & 0x0f;\n nibbles.push(n1, n2);\n checksum += 15 - n1 + (15 - n2);\n }\n\n const c1 = (checksum >> 8) & 0x0f;\n const c2 = (checksum >> 4) & 0x0f;\n const c3 = checksum & 0x0f;\n nibbles.push(c1, c2, c3);\n\n const privParts = privateKeyStr.split(';');\n if (privParts.length !== WOTS_LEN) throw new Error('Invalid private key length.');\n\n // Derive a stable fingerprint for this key from its first element to track reuse.\n // We fingerprint the public key equivalent (hash chain end of part[0]) so that\n // the fingerprint is independent of the private key bytes themselves.\n const keyFingerprint = createHash('sha256').update(privParts[0]).digest('hex');\n if (_usedWotsKeys.has(keyFingerprint)) {\n throw new Error(\n 'WOTS_KEY_REUSE: This WOTS private key has already been used to sign a message. ' +\n 'Reusing a WOTS key leaks private key material and breaks the security of the scheme. ' +\n 'Generate a new key pair with generatePQCKeyPair() for each message.',\n );\n }\n _usedWotsKeys.add(keyFingerprint);\n\n const sigParts: string[] = [];\n for (let i = 0; i < WOTS_LEN; i++) {\n const n = nibbles[i];\n let current = Buffer.from(privParts[i], 'hex');\n for (let j = 0; j < n; j++) {\n current = createHash('sha256').update(current).digest();\n }\n sigParts.push(current.toString('hex'));\n }\n return sigParts.join(';');\n};\n\n/**\n * Verifies a Winternitz One-Time Signature (WOTS) against a message and public key.\n *\n * This operation is safe to call multiple times for the same public key — verification\n * does not consume the key or leak any private key material.\n *\n * @param data - The original message that was signed.\n * @param signature - The signature string returned by `signPQC`.\n * @param publicKey - The public key string returned by `generatePQCKeyPair`.\n * @returns `true` if the signature is valid for the given message and public key.\n */\nexport const verifyPQCSignature = (\n data: Buffer | string,\n signature: string,\n publicKey: string,\n): boolean => {\n try {\n const msgHash = createHash('sha256').update(data).digest();\n const nibbles: number[] = [];\n let checksum = 0;\n for (let i = 0; i < 32; i++) {\n const byte = msgHash[i];\n const n1 = byte >> 4;\n const n2 = byte & 0x0f;\n nibbles.push(n1, n2);\n checksum += 15 - n1 + (15 - n2);\n }\n\n const c1 = (checksum >> 8) & 0x0f;\n const c2 = (checksum >> 4) & 0x0f;\n const c3 = checksum & 0x0f;\n nibbles.push(c1, c2, c3);\n\n const sigParts = signature.split(';');\n const pubParts = publicKey.split(';');\n if (sigParts.length !== WOTS_LEN || pubParts.length !== WOTS_LEN) return false;\n\n for (let i = 0; i < WOTS_LEN; i++) {\n const n = nibbles[i];\n let current = Buffer.from(sigParts[i], 'hex');\n for (let j = 0; j < 15 - n; j++) {\n current = createHash('sha256').update(current).digest();\n }\n const expected = Buffer.from(pubParts[i], 'hex');\n if (!timingSafeEqual(current, expected)) return false;\n }\n return true;\n } catch {\n return false;\n }\n};\n\n/**\n * Password hashing.\n */\nexport const hashPassword = async (password: string, salt?: string) => {\n const actualSalt = salt || generateToken(16);\n const derivedKey = (await scryptAsync(password, actualSalt, 64)) as Buffer;\n return { hash: derivedKey.toString('hex'), salt: actualSalt };\n};\n\n/**\n * verification.\n */\nexport const verifyPassword = async (\n password: string,\n storedHash: string,\n salt: string,\n): Promise<boolean> => {\n const { hash } = await hashPassword(password, salt);\n const hashBuffer = Buffer.from(hash, 'hex');\n const storedBuffer = Buffer.from(storedHash, 'hex');\n if (hashBuffer.length !== storedBuffer.length) return false;\n return timingSafeEqual(hashBuffer, storedBuffer);\n};\n\n/**\n * SHA-256.\n */\nexport const sha256 = (data: string): string => {\n return createHash('sha256').update(data).digest('hex');\n};\n\nconst startWorkerIfChild = async () => {\n try {\n const { isMainThread, parentPort, workerData } = await import('node:worker_threads');\n if (!isMainThread && parentPort) {\n try {\n const { functionName, args = [] } = workerData || {};\n if (functionName === 'hashPassword') {\n const [password, salt] = args;\n if (password === undefined) {\n parentPort.postMessage({ status: 'success' });\n } else {\n hashPassword(password, salt)\n .then((result) => {\n parentPort.postMessage({ status: 'success', result });\n })\n .catch((err) => {\n parentPort.postMessage({ status: 'error', error: err.message });\n });\n }\n } else if (functionName === 'splitSecret') {\n const [secret, sharesCount, threshold] = args;\n const result = splitSecret(secret, sharesCount, threshold);\n parentPort.postMessage({ status: 'success', result });\n } else if (functionName === 'reconstructSecret') {\n const [shares] = args;\n const result = reconstructSecret(shares);\n parentPort.postMessage({ status: 'success', result: result.toString('hex') });\n } else {\n parentPort.postMessage({ status: 'error', error: `Unknown function: ${functionName}` });\n }\n } catch (err: any) {\n parentPort.postMessage({ status: 'error', error: err.message });\n }\n }\n } catch {\n // node:worker_threads is not supported/needed in this environment, skip execution\n }\n};\n\nstartWorkerIfChild();\n","/**\n * Lightweight OpenTelemetry-compatible telemetry hook system for Mitigator.\n *\n * This module provides a zero-dependency, zero-overhead telemetry integration point.\n * By default all hooks are no-ops. Consumers inject their own tracer/metrics provider\n * via `setTelemetryProvider()` — works with any OTEL SDK, Datadog, Prometheus, or custom.\n *\n * @example\n * ```ts\n * import { setTelemetryProvider } from 'mitigator/telemetry';\n * import { trace, metrics } from '@opentelemetry/api';\n *\n * const tracer = trace.getTracer('mitigator');\n * const meter = metrics.getMeter('mitigator');\n * const rateLimitCounter = meter.createCounter('mitigator.rate_limit.blocked');\n * const securityEventCounter = meter.createCounter('mitigator.security.events');\n *\n * setTelemetryProvider({\n * onRateLimitBlocked(id, severity) {\n * rateLimitCounter.add(1, { id, severity });\n * },\n * onSecurityEvent(id, weight) {\n * securityEventCounter.add(weight, { id });\n * },\n * onKillSwitchTriggered(id) {\n * const span = tracer.startSpan('mitigator.kill_switch');\n * span.setAttribute('actor.id', id);\n * span.end();\n * },\n * onWorkerSpawned(functionName) {\n * // track worker thread usage\n * },\n * });\n * ```\n */\n\n/**\n * Telemetry event hooks that Mitigator calls at key security decision points.\n * All methods are optional — implement only what your observability stack needs.\n */\nexport interface MitigatorTelemetryProvider {\n /**\n * Called when a request is blocked by `AdaptiveRateLimiter.isLimited()`.\n * @param id The client ID (IP, session, etc.) that was blocked.\n * @param severity `'penalty'` if the actor is high-risk, `'standard'` otherwise.\n */\n onRateLimitBlocked?(id: string, severity: 'standard' | 'penalty'): void;\n\n /**\n * Called when `AdaptiveRateLimiter.recordSecurityEvent()` is invoked.\n * @param id The client ID receiving the security score increment.\n * @param weight The weight of the security event.\n */\n onSecurityEvent?(id: string, weight: number): void;\n\n /**\n * Called immediately before `AdaptiveRateLimiter.triggerGlobalKillSwitch()` writes.\n * @param id The client ID being permanently blocked.\n */\n onKillSwitchTriggered?(id: string): void;\n\n /**\n * Called each time `runIsolatedCrypto` acquires a worker thread slot.\n * @param functionName The crypto function being dispatched to the worker.\n */\n onWorkerSpawned?(functionName: string): void;\n}\n\n/** No-op provider used when no telemetry is configured. */\nconst NOOP_PROVIDER: Required<MitigatorTelemetryProvider> = {\n onRateLimitBlocked: () => {},\n onSecurityEvent: () => {},\n onKillSwitchTriggered: () => {},\n onWorkerSpawned: () => {},\n};\n\nlet _provider: MitigatorTelemetryProvider = NOOP_PROVIDER;\n\n/**\n * Registers a telemetry provider that Mitigator will call at key security events.\n *\n * Call this once at application startup, before any Mitigator functions are used.\n * Replaces any previously registered provider.\n *\n * @param provider An object implementing any subset of `MitigatorTelemetryProvider`.\n */\nexport const setTelemetryProvider = (provider: MitigatorTelemetryProvider): void => {\n _provider = provider;\n};\n\n/**\n * Resets the telemetry provider to the built-in no-op (useful in tests).\n */\nexport const resetTelemetryProvider = (): void => {\n _provider = NOOP_PROVIDER;\n};\n\n/**\n * Internal accessor used by Mitigator modules to emit telemetry events.\n * Not part of the public API — use `setTelemetryProvider` instead.\n *\n * @internal\n */\nexport const getTelemetryProvider = (): MitigatorTelemetryProvider => _provider;\n","import { resolve, relative, isAbsolute } from 'node:path';\n\n/**\n * Standard Magic Numbers for common file types.\n */\nexport const MAGIC_NUMBERS = {\n PNG: [0x89, 0x50, 0x4e, 0x47],\n JPEG: [0xff, 0xd8, 0xff],\n PDF: [0x25, 0x50, 0x44, 0x46],\n GIF: [0x47, 0x49, 0x46, 0x38],\n};\n\n/**\n * Resolves a path relative to a root directory and ensures it doesn't escape the root.\n */\nexport const resolveSafePath = (rootDir: string, userInputPath: string): string => {\n const absoluteRoot = resolve(rootDir);\n const resolvedPath = resolve(absoluteRoot, userInputPath);\n\n const relativePath = relative(absoluteRoot, resolvedPath);\n\n if (relativePath.startsWith('..') || isAbsolute(relativePath)) {\n throw new Error('Security Error: Path traversal attempt detected.');\n }\n\n return resolvedPath;\n};\n\n/**\n * Verifies that a file's magic numbers match the expected type.\n * This is much more secure than trusting file extensions or MIME types.\n *\n * @param filePath The path to the file.\n * @param expectedMagic The array of bytes to match.\n * @returns true if the file matches.\n */\nexport const verifyMagicNumber = async (\n filePath: string,\n expectedMagic: number[],\n): Promise<boolean> => {\n const fs = await import('node:fs/promises');\n const handle = await fs.open(filePath, 'r');\n try {\n const buffer = Buffer.alloc(expectedMagic.length);\n await handle.read(buffer, 0, expectedMagic.length, 0);\n\n return expectedMagic.every((byte, index) => buffer[index] === byte);\n } finally {\n await handle.close();\n }\n};\n\n/**\n * Safely reads a file from a root-locked directory.\n */\nexport const safeRead = async (rootDir: string, filePath: string): Promise<string> => {\n const fs = await import('node:fs/promises');\n const safePath = resolveSafePath(rootDir, filePath);\n return fs.readFile(safePath, 'utf8');\n};\n\n/**\n * Checks if a path is safe (within the root) without throwing.\n */\nexport const isPathSafe = (rootDir: string, filePath: string): boolean => {\n try {\n resolveSafePath(rootDir, filePath);\n return true;\n } catch {\n return false;\n }\n};\n","import { createHash, randomInt, randomBytes } from 'node:crypto';\nimport * as https from 'node:https';\n\n/**\n * Checks if a request is over HTTPS.\n */\nexport const isSecure = (\n url?: string,\n headers: Record<string, string | string[] | undefined> = {},\n): boolean => {\n if (url?.startsWith('https://')) return true;\n const proto = headers['x-forwarded-proto'];\n if (typeof proto === 'string' && proto.toLowerCase() === 'https') return true;\n return false;\n};\n\n/**\n * Normalizes a URL.\n */\nexport const normalizeUrl = (url: string): string => {\n try {\n const parsed = new URL(url);\n parsed.pathname = parsed.pathname.replaceAll('//', '/');\n return parsed.toString();\n } catch {\n return url.replaceAll('//', '/');\n }\n};\n\n/**\n * Hardened HTTPS Tunneling Helper.\n * Configures an outgoing https.request with strictly-enforced security options,\n * including TLS 1.3, strong ciphers, and OCSP stapling if supported.\n *\n * @param options Custom https.RequestOptions to extend.\n * @returns {https.RequestOptions} The hardened options.\n */\nexport const getHardenedRequestOptions = (\n options: https.RequestOptions = {},\n): https.RequestOptions => {\n return {\n ...options,\n minVersion: 'TLSv1.3',\n ciphers: 'TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256',\n rejectUnauthorized: true,\n };\n};\n\n/**\n * JA3 TLS Fingerprinting.\n */\nexport const generateTLSFingerprint = (req: any): string => {\n const headers = req.headers || {};\n const fingerprintParts = [\n headers['user-agent'] || '',\n headers['accept'] || '',\n headers['accept-language'] || '',\n headers['accept-encoding'] || '',\n headers['connection'] || '',\n headers['upgrade-insecure-requests'] || '',\n ];\n return createHash('sha256').update(fingerprintParts.join('|')).digest('hex');\n};\n\n/**\n * Analyzestraffic for DoS patterns.\n */\nexport const analyzeDoSThreat = (req: any): boolean => {\n const headers = req.headers || {};\n if (headers['transfer-encoding'] && headers['content-length']) return true;\n if (headers['connection'] === 'keep-alive' && !headers['content-length'] && req.method === 'POST')\n return true;\n return false;\n};\n\n/**\n * Generates client fingerprint.\n */\nexport const generateFingerprint = (\n reqHeaders: Record<string, string | string[] | undefined>,\n ip: string,\n): string => {\n const parts = [\n ip,\n reqHeaders['user-agent'] || 'unknown',\n reqHeaders['accept-language'] || 'unknown',\n reqHeaders['accept-encoding'] || 'unknown',\n reqHeaders['sec-ch-ua'] || 'unknown',\n reqHeaders['sec-ch-ua-platform'] || 'unknown',\n ];\n return createHash('sha256').update(parts.join('|')).digest('hex');\n};\n\n/**\n * Projects noise.\n */\nexport const projectNoise = (obj: any): any => {\n if (typeof obj !== 'object' || obj === null) return obj;\n const noiseCount = randomInt(1, 4);\n const result = { ...obj };\n for (let i = 0; i < noiseCount; i++) {\n const noiseKey = `_sk_${randomBytes(4).toString('hex')}`;\n const noiseValue = randomBytes(8).toString('base64');\n result[noiseKey] = noiseValue;\n }\n return result;\n};\n\n/**\n * Safe Redirect.\n */\nexport const isSafeRedirect = (url: string, allowedHosts: string[] = []): boolean => {\n if (url.startsWith('/')) return !url.startsWith('//');\n try {\n const parsed = new URL(url);\n return allowedHosts.includes(parsed.hostname);\n } catch {\n return false;\n }\n};\n\n/**\n * SRI Hash.\n */\nexport const generateSRI = (\n data: string | Buffer,\n algorithm: 'sha256' | 'sha384' | 'sha512' = 'sha384',\n): string => {\n const hash = createHash(algorithm).update(data).digest('base64');\n return `${algorithm}-${hash}`;\n};\n","import { getTelemetryProvider } from '../utils/telemetry.js';\n\n/**\n * A simple in-memory Store for the rate limiter.\n */\nexport interface RateLimitStore {\n increment(key: string, amount?: number): Promise<number>;\n get(key: string): Promise<number | undefined>;\n reset(key: string): Promise<void>;\n setTTL(key: string, value: number, ttlMs: number): Promise<void>;\n}\n\nexport class MemoryStore implements RateLimitStore {\n private readonly hits = new Map<string, { count: number; expires: number }>();\n private readonly gcInterval: NodeJS.Timeout;\n\n constructor(private readonly windowMs: number) {\n // Run Garbage Collection every minute\n this.gcInterval = setInterval(() => this.gc(), 60000);\n // Ensure the timer doesn't keep the Node.js event loop alive\n /* v8 ignore next 3 */\n if (this.gcInterval.unref) {\n this.gcInterval.unref();\n }\n }\n\n private gc() {\n const now = Date.now();\n for (const [key, hit] of this.hits.entries()) {\n if (now > hit.expires) {\n this.hits.delete(key);\n }\n }\n }\n\n async increment(key: string, amount: number = 1): Promise<number> {\n const now = Date.now();\n const hit = this.hits.get(key);\n\n if (!hit || now > hit.expires) {\n this.hits.set(key, { count: amount, expires: now + this.windowMs });\n return amount;\n }\n\n hit.count += amount;\n return hit.count;\n }\n\n async get(key: string): Promise<number | undefined> {\n const hit = this.hits.get(key);\n if (!hit || Date.now() > hit.expires) return undefined;\n return hit.count;\n }\n\n async reset(key: string): Promise<void> {\n this.hits.delete(key);\n }\n\n async setTTL(key: string, value: number, ttlMs: number): Promise<void> {\n this.hits.set(key, { count: value, expires: Date.now() + ttlMs });\n }\n\n // Cleanup method if needed\n destroy() {\n clearInterval(this.gcInterval);\n }\n}\n\n/**\n * Redis Store implementation for the rate limiter.\n * Expects a Redis-compatible client (e.g., from 'ioredis' or 'redis').\n */\n/**\n * Minimal structural interface for a Redis-compatible client.\n *\n * This is intentionally narrow — it describes only the API surface that\n * `RedisStore` actually uses. Any client that satisfies this interface\n * (e.g. `ioredis`, `node-redis` v4) will work without importing their\n * types as a dependency.\n */\nexport interface RedisMultiChain {\n incrby(key: string, amount: number): RedisMultiChain;\n pttl(key: string): RedisMultiChain;\n exec(): Promise<Array<[error: Error | null, result: unknown]>>;\n}\n\nexport interface RedisClientLike {\n multi(): RedisMultiChain;\n get(key: string): Promise<string | null>;\n del(key: string): Promise<number>;\n set(key: string, value: number | string, mode: 'PX', ttlMs: number): Promise<string | null>;\n pexpire(key: string, ttlMs: number): Promise<number>;\n}\n\n/**\n * Redis Store implementation for the rate limiter.\n * Accepts any `RedisClientLike`-compatible client (e.g. `ioredis`, `redis` v4).\n */\nexport class RedisStore implements RateLimitStore {\n constructor(\n private readonly redisClient: RedisClientLike,\n private readonly windowMs: number,\n private readonly prefix: string = 'rl:',\n ) {}\n\n async increment(key: string, amount: number = 1): Promise<number> {\n const prefixedKey = this.prefix + key;\n const multi = this.redisClient.multi();\n multi.incrby(prefixedKey, amount);\n multi.pttl(prefixedKey);\n const results = await multi.exec();\n\n // Exact structure of results depends on the redis client (ioredis vs redis v4).\n // Assuming standard ioredis format: [[null, value], [null, ttl]]\n const count = Number.parseInt(results[0][1] as string, 10);\n const ttl = Number.parseInt(results[1][1] as string, 10);\n\n if (ttl === -1) {\n await this.redisClient.pexpire(prefixedKey, this.windowMs);\n }\n return count;\n }\n\n async get(key: string): Promise<number | undefined> {\n const val = await this.redisClient.get(this.prefix + key);\n return val ? Number.parseInt(val, 10) : undefined;\n }\n\n async reset(key: string): Promise<void> {\n await this.redisClient.del(this.prefix + key);\n }\n\n async setTTL(key: string, value: number, ttlMs: number): Promise<void> {\n const prefixedKey = this.prefix + key;\n await this.redisClient.set(prefixedKey, value, 'PX', ttlMs);\n }\n}\n\n/**\n * TokenBucket implementation for smooth rate limiting.\n */\nexport class TokenBucket {\n private readonly buckets = new Map<string, { tokens: number; lastRefill: number }>();\n\n constructor(\n private readonly capacity: number,\n private readonly refillRatePerSecond: number,\n ) {}\n\n async consume(id: string, tokens: number = 1): Promise<boolean> {\n const now = Date.now();\n const bucket = this.buckets.get(id);\n\n if (bucket) {\n const delta = (now - bucket.lastRefill) / 1000;\n const refill = delta * this.refillRatePerSecond;\n bucket.tokens = Math.min(this.capacity, bucket.tokens + refill);\n bucket.lastRefill = now;\n } else {\n const newBucket = { tokens: this.capacity, lastRefill: now };\n if (newBucket.tokens >= tokens) {\n newBucket.tokens -= tokens;\n this.buckets.set(id, newBucket);\n return true;\n }\n this.buckets.set(id, newBucket);\n return false;\n }\n\n if (bucket.tokens >= tokens) {\n bucket.tokens -= tokens;\n this.buckets.set(id, bucket);\n return true;\n }\n\n this.buckets.set(id, bucket);\n return false;\n }\n}\n\n/**\n * Adaptive RateLimiter implementation with Global Kill-Switch and IR Hook support.\n */\nexport class AdaptiveRateLimiter {\n private readonly store: RateLimitStore;\n private readonly securityStore: RateLimitStore;\n private readonly burstStore: RateLimitStore;\n private readonly ipCheckers: ((ip: string) => Promise<boolean>)[] = [];\n\n constructor(\n private readonly config: {\n standardLimit: number;\n penaltyLimit: number;\n windowMs: number;\n securityThreshold: number;\n burstThreshold: number;\n },\n store?: RateLimitStore,\n securityStore?: RateLimitStore,\n burstStore?: RateLimitStore,\n ) {\n this.store = store || new MemoryStore(config.windowMs);\n this.securityStore = securityStore || new MemoryStore(config.windowMs);\n this.burstStore = burstStore || new MemoryStore(config.windowMs * 10);\n }\n\n /**\n * Automates Incident Response by globally \"killing\" a session or IP.\n * This sets an infinite (effectively 1-year) block on the ID.\n *\n * @param id The client ID to block.\n *\n * @remarks\n * **Persistence warning**: If the underlying store is `MemoryStore` (the default),\n * the block is held in process memory and will be **lost on process restart**.\n * For a persistent kill-switch that survives restarts and works across multiple\n * instances, pass a `RedisStore` as the `store` and `securityStore` arguments\n * to the `AdaptiveRateLimiter` constructor.\n *\n * @see {@link RedisStore} for a production-grade persistent store.\n */\n async triggerGlobalKillSwitch(id: string): Promise<void> {\n getTelemetryProvider().onKillSwitchTriggered?.(id);\n const ONE_YEAR_MS = 365 * 24 * 60 * 60 * 1000;\n await this.securityStore.setTTL(`${id}:score`, 99999, ONE_YEAR_MS);\n await this.store.setTTL(id, 99999, ONE_YEAR_MS);\n console.warn(`Mitigator: Global Kill-Switch triggered for actor: ${id}`);\n }\n\n registerIPChecker(checker: (ip: string) => Promise<boolean>): void {\n this.ipCheckers.push(checker);\n }\n\n async recordSecurityEvent(id: string, weight: number = 1): Promise<void> {\n getTelemetryProvider().onSecurityEvent?.(id, weight);\n await this.securityStore.increment(`${id}:score`, weight);\n }\n\n async isLimited(id: string): Promise<boolean> {\n for (const checker of this.ipCheckers) {\n if (await checker(id)) return true;\n }\n\n const score = (await this.securityStore.get(`${id}:score`)) || 0;\n const bursts = (await this.burstStore.get(`${id}:bursts`)) || 0;\n\n const isCompromised =\n score >= this.config.securityThreshold || bursts >= this.config.burstThreshold;\n const currentLimit = isCompromised ? this.config.penaltyLimit : this.config.standardLimit;\n\n const count = await this.store.increment(id);\n\n if (count > currentLimit) {\n if (count === currentLimit + 1) {\n await this.burstStore.increment(`${id}:bursts`, 1);\n }\n getTelemetryProvider().onRateLimitBlocked?.(id, isCompromised ? 'penalty' : 'standard');\n return true;\n }\n\n return false;\n }\n\n async isHighRisk(id: string): Promise<boolean> {\n const score = (await this.securityStore.get(`${id}:score`)) || 0;\n const bursts = (await this.burstStore.get(`${id}:bursts`)) || 0;\n return score >= this.config.securityThreshold || bursts >= this.config.burstThreshold;\n }\n}\n\n/**\n * Basic Sliding Window RateLimiter for backward compatibility.\n */\nexport class RateLimiter {\n private readonly store: RateLimitStore;\n\n constructor(\n private readonly limit: number,\n private readonly windowMs: number,\n store?: RateLimitStore,\n ) {\n this.store = store || new MemoryStore(windowMs);\n }\n\n async isLimited(id: string): Promise<boolean> {\n const count = await this.store.increment(id);\n return count > this.limit;\n }\n}\n","/**\n * Prototype pollution safe JSON parsing with depth limiting to prevent\n * \"JSON Depth\" or \"Billion Laughs\" style DoS attacks.\n */\nexport const parse = (text: string, maxDepth: number = 10): any => {\n const obj = JSON.parse(text, (key, value) => {\n if (key === '__proto__' || key === 'constructor' || key === 'prototype') {\n return undefined;\n }\n return value;\n });\n\n if (getDepth(obj) > maxDepth) {\n throw new Error('Security Error: JSON depth limit exceeded (DoS protection).');\n }\n\n return obj;\n};\n\n/**\n * Calculates the maximum depth of an object to detect nested-complexity attacks.\n */\nexport const getDepth = (obj: any): number => {\n if (obj === null || typeof obj !== 'object') return 0;\n\n let max = 0;\n for (const key in obj) {\n if (Object.hasOwn(obj, key)) {\n max = Math.max(max, getDepth(obj[key]));\n }\n }\n return 1 + max;\n};\n\n/**\n * Recursively checks an object for prototype pollution keys.\n */\nexport const containsPollution = (obj: any): boolean => {\n if (obj === null || typeof obj !== 'object') return false;\n\n for (const key in obj) {\n if (key === '__proto__' || key === 'constructor' || key === 'prototype') {\n return true;\n }\n if (containsPollution(obj[key])) {\n return true;\n }\n }\n return false;\n};\n","/**\n * Keys that can be used for prototype pollution attacks.\n */\nconst DANGEROUS_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\n\n/**\n * Checks if a value is a plain object.\n */\nconst isObject = (val: any): val is Record<string, any> => {\n return val !== null && typeof val === 'object' && !Array.isArray(val);\n};\n\n/**\n * Deep merges source into target securely, preventing:\n * 1. Prototype pollution (key filtering)\n * 2. Infinite loops (circular reference detection)\n *\n * @param target The target object to merge into.\n * @param source The source object to merge from.\n * @param seen WeakSet to track seen objects for circular reference detection.\n * @returns The merged object.\n */\nexport const merge = <T extends object, S extends object>(\n target: T,\n source: S,\n seen: WeakSet<object> = new WeakSet(),\n): T & S => {\n if (seen.has(source)) {\n throw new Error(\n 'Security Error: Circular reference detected during deep merge (DoS prevention).',\n );\n }\n\n const output = { ...target } as any;\n\n if (isObject(target) && isObject(source)) {\n seen.add(source);\n\n Object.keys(source).forEach((key) => {\n // Prevent prototype pollution\n if (DANGEROUS_KEYS.has(key)) {\n return;\n }\n\n const sourceValue = (source as any)[key];\n const targetValue = (target as any)[key];\n\n if (isObject(sourceValue) && isObject(targetValue)) {\n output[key] = merge(targetValue, sourceValue, seen);\n } else {\n output[key] = sourceValue;\n }\n });\n }\n\n return output;\n};\n\n/**\n * Recursively removes prototype-related keys from an object to sanitize untrusted input.\n */\nexport const sanitizeObject = <T>(obj: T, seen: WeakSet<object> = new WeakSet()): T => {\n if (obj === null || typeof obj !== 'object') return obj;\n\n if (seen.has(obj)) {\n throw new Error('Security Error: Circular reference detected during object sanitization.');\n }\n\n if (Array.isArray(obj)) {\n seen.add(obj);\n return obj.map((item) => sanitizeObject(item, seen)) as any;\n }\n\n seen.add(obj);\n const result: any = {};\n for (const [key, value] of Object.entries(obj)) {\n if (DANGEROUS_KEYS.has(key)) continue;\n result[key] = sanitizeObject(value, seen);\n }\n return result;\n};\n\n/**\n * Deep freezes an object to prevent any modifications.\n */\nexport const deepFreeze = <T extends object>(obj: T): T => {\n Object.getOwnPropertyNames(obj).forEach((name) => {\n const prop = (obj as any)[name];\n if (prop !== null && typeof prop === 'object') {\n deepFreeze(prop);\n }\n });\n return Object.freeze(obj);\n};\n","import { createHash } from 'node:crypto';\n\n/**\n * Common sensitive keys for redaction.\n */\nexport const SENSITIVE_KEYS = new Set([\n 'password',\n 'token',\n 'secret',\n 'key',\n 'authorization',\n 'apiKey',\n 'access_token',\n 'refresh_token',\n 'cvv',\n 'card_number',\n 'ssn',\n]);\n\n/**\n * Redacts sensitive keys.\n */\nexport const redact = <T>(obj: T, redactKeys: Set<string> = SENSITIVE_KEYS): T => {\n if (obj === null || typeof obj !== 'object') return obj;\n if (Array.isArray(obj)) return obj.map((item) => redact(item, redactKeys)) as any;\n const result: any = {};\n for (const [key, value] of Object.entries(obj)) {\n if (redactKeys.has(key.toLowerCase())) {\n result[key] = '[REDACTED]';\n } else if (typeof value === 'object') {\n result[key] = redact(value, redactKeys);\n } else {\n result[key] = value;\n }\n }\n return result;\n};\n\n/**\n * SecureError wrapper.\n */\nexport class SecureError extends Error {\n public readonly code: string;\n public readonly userMessage: string;\n constructor(\n message: string,\n code: string = 'INTERNAL_ERROR',\n userMessage: string = 'An unexpected error occurred.',\n ) {\n super(message);\n this.name = 'SecureError';\n this.code = code;\n this.userMessage = userMessage;\n if (process.env.NODE_ENV === 'production') this.stack = '';\n }\n toJSON() {\n return { error: true, code: this.code, message: this.userMessage };\n }\n}\n\n/**\n * Normalizes an error.\n */\nexport const normalizeError = (error: any): SecureError => {\n if (error instanceof SecureError) return error;\n return new SecureError(error?.message || 'Unknown error');\n};\n\n/**\n * Memory-Wiping (Anti-Forensics) utility.\n * Explicitly overwrites the content of a Buffer or Uint8Array with zero bytes.\n * This is the ultimate \"last step\" for protecting high-entropy key material.\n *\n * @param buf The Buffer or Uint8Array to zero-out.\n */\nexport const wipeBuffer = (buf: Buffer | Uint8Array | any[]): void => {\n if (Array.isArray(buf)) {\n for (let i = 0; i < buf.length; i++) buf[i] = 0;\n } else if (buf instanceof Buffer || buf instanceof Uint8Array) {\n buf.fill(0);\n }\n};\n\n/**\n * Minimal logger interface for dependency injection.\n * Any object with `error` and `warn` methods satisfies this —\n * e.g. `console`, `winston`, `pino`, or a custom OTEL-aware logger.\n */\nexport interface MinimalLogger {\n error(message: string, ...args: unknown[]): void;\n warn(message: string, ...args: unknown[]): void;\n}\n\n/**\n * Self-healing configuration monitor.\n *\n * Runs `auditConfig` on the supplied configuration at a fixed interval and\n * logs any detected drift through the provided `logger`.\n *\n * @param config The configuration object to audit.\n * @param type The configuration type ('db' | 'redis' | 'auth').\n * @param intervalMs How often to run the audit (default: 10 minutes).\n * @param logger Optional logger to receive drift alerts. Defaults to `console`.\n * Inject a structured logger (Winston, Pino, OTEL) for production.\n *\n * @example\n * // Default — uses console\n * startSelfHealingMonitor(dbConfig, 'db');\n *\n * // Production — inject your logger\n * startSelfHealingMonitor(dbConfig, 'db', 600_000, pinoLogger);\n */\nexport const startSelfHealingMonitor = (\n config: Parameters<typeof auditConfig>[0],\n type: Parameters<typeof auditConfig>[1],\n intervalMs: number = 600000,\n logger: MinimalLogger = console,\n): void => {\n setInterval(() => {\n const issues = auditConfig(config, type);\n if (issues.length > 0) {\n logger.error('MITIGATOR CRITICAL: Self-healing monitor detected insecure config drift!');\n issues.forEach((issue) => logger.error(`- ${issue}`));\n }\n }, intervalMs).unref();\n};\n\n/**\n * SQL Injection Hardening.\n */\nexport const enforceSafeQuery = (query: string, params: any[]): void => {\n if ((!params || params.length === 0) && query.toLowerCase().includes('where')) {\n const suspicious = [\"'\", '\"', '=', '--', ';'];\n if (suspicious.some((char) => query.includes(char))) {\n throw new SecureError(\n 'Security Violation: Unparameterized query detected.',\n 'SQL_INJECTION_RISK',\n );\n }\n }\n};\n\n/**\n * Deterministic digit substitution using SHA-256 offset encoding.\n *\n * @remarks\n * **This is NOT Format-Preserving Encryption (FPE).**\n * It does NOT implement NIST SP 800-38G (FF1/FF3-1). It is a lightweight,\n * deterministic digit-level obfuscation function suitable for display masking\n * and non-compliance-grade transformations only.\n *\n * Do NOT use this for PCI-DSS, HIPAA, or any standard requiring certified FPE.\n *\n * @param input A string of decimal digit characters (0–9) to transform.\n * @param secret A secret key string used to derive the substitution offsets.\n * @returns A digit-length-preserving transformed string.\n */\nexport const deterministicDigitTransform = (input: string, secret: string): string => {\n const hash = createHash('sha256').update(input).update(secret).digest('hex');\n let result = '';\n for (let i = 0; i < input.length; i++) {\n const digit = Number.parseInt(input[i]);\n const offset = Number.parseInt(hash[i % hash.length], 16);\n result += ((digit + offset) % 10).toString();\n }\n return result;\n};\n\n/**\n * Environment security check.\n */\nexport const checkSecureEnv = (): void => {\n const isProd = process.env.NODE_ENV === 'production';\n if (isProd) {\n if (!process.env.SESSION_SECRET || process.env.SESSION_SECRET.length < 32) {\n console.warn('Security Warning: SESSION_SECRET is missing or too short.');\n }\n }\n};\n\n/**\n * Configuration Auditor.\n */\nexport const auditConfig = (config: any, type: 'db' | 'redis' | 'auth'): string[] => {\n const issues: string[] = [];\n if (type === 'db') {\n if (config.ssl === false) issues.push('Database SSL is disabled.');\n if (config.port === 3306 || config.port === 5432)\n issues.push('Database is using a default port.');\n } else if (type === 'auth') {\n if (config.allowInsecurePasswordReset) issues.push('Allowing insecure password reset.');\n }\n return issues;\n};\n\n/**\n * Global prototype lockdown.\n */\nexport const lockdownPrototypes = (): void => {\n try {\n Object.freeze(Object.prototype);\n Object.freeze(Array.prototype);\n Object.freeze(String.prototype);\n } catch {\n console.error('Mitigator Error: Failed to lockdown prototypes.');\n }\n};\n\n/**\n * mTLS Helper.\n */\nexport const createMTLSOptions = (serverCert: Buffer, serverKey: Buffer, caCert: Buffer) => {\n return {\n cert: serverCert,\n key: serverKey,\n ca: caCert,\n requestCert: true,\n rejectUnauthorized: true,\n };\n};\n\n/**\n * Security preset.\n */\nexport const standardSecurityPreset = {\n trustProxy: true,\n strictTransportSecurity: { maxAge: 31536000, includeSubDomains: true, preload: true },\n contentSecurityPolicy: true,\n referrerPolicy: 'strict-origin-when-cross-origin' as const,\n};\n","import { createHash } from 'node:crypto';\nimport { SecureError, redact } from './index.js';\nimport * as headers from '../headers/index.js';\nimport * as sanitize from '../sanitize/index.js';\nimport * as safeJson from '../safe-json/index.js';\nimport * as validate from '../validate/index.js';\n\nimport { RateLimiter, MemoryStore } from '../rate-limit/index.js';\n\n/**\n * A lightweight Express middleware preset.\n */\nexport const expressMiddleware = (\n options: { rateLimit?: boolean; rateLimitWindowMs?: number; rateLimitMax?: number } = {},\n) => {\n const limiter = options.rateLimit\n ? new RateLimiter(\n options.rateLimitMax || 100,\n options.rateLimitWindowMs || 60000,\n new MemoryStore(options.rateLimitWindowMs || 60000),\n )\n : null;\n\n return async (req: any, res: any, next: any) => {\n Object.entries(headers.standardHeaders).forEach(([key, value]) => {\n res.setHeader(key, value);\n });\n\n if (limiter) {\n const ip = req.ip || req.connection.remoteAddress || 'unknown';\n if (await limiter.isLimited(ip)) {\n return res.status(429).json({ error: 'Too Many Requests' });\n }\n }\n\n try {\n if (req.body && typeof req.body === 'object') {\n if (validate.scanForSecrets(req.body)) {\n return next(\n new SecureError('Security Violation: Potential secret leakage detected.', 'BAD_INPUT'),\n );\n }\n }\n } catch {\n return next(new SecureError('Security Violation: Suspicious input detected.', 'BAD_INPUT'));\n }\n req.mitigator = {\n sanitize: (html: string) => sanitize.sanitizeHtml(html),\n safeJson: (text: string) => safeJson.parse(text),\n };\n next();\n };\n};\n\n/**\n * Next.js Edge Middleware Preset.\n * Note: Next.js edge runtime doesn't support all Node APIs, so we keep it lightweight.\n */\nexport const nextJsMiddleware = (_req: any, res: any) => {\n Object.entries(headers.standardHeaders).forEach(([key, value]) => {\n res.headers.set(key, value);\n });\n return res;\n};\n\n/**\n * Global response error handler for Express.\n */\nexport const expressErrorHandler = (err: any, _req: any, res: any, _next: any) => {\n const secureErr = err instanceof SecureError ? err : new SecureError(err.message);\n res.status(secureErr.code === 'BAD_INPUT' ? 400 : 500).json(secureErr.toJSON());\n};\n\n/**\n * Secure Logger with Cryptographic Hash-Chain (Tamper-Proof Logs).\n * Every entry is linked to the previous one via a SHA-256 hash, making it\n * mathematically detectable if an attacker deletes or modifies log entries.\n */\nexport class SecureLoggerChain {\n private lastHash: string = '';\n\n constructor(private readonly baseLogger: { info: Function; error: Function; warn: Function }) {\n // Initialize with a unique \"seed\" hash\n this.lastHash = createHash('sha256').update(Date.now().toString()).digest('hex');\n }\n\n private chain(msg: string, data: any): string {\n const payload = JSON.stringify({ msg, data, prev: this.lastHash });\n this.lastHash = createHash('sha256').update(payload).digest('hex');\n return this.lastHash;\n }\n\n info(msg: string, data?: any) {\n const hash = this.chain(msg, data);\n this.baseLogger.info(`[CHAIN:${hash}] ${msg}`, redact(data));\n }\n\n warn(msg: string, data?: any) {\n if (validate.scanForSecrets(data)) {\n this.baseLogger.warn('CRITICAL: Secret leakage blocked!');\n return;\n }\n const hash = this.chain(msg, data);\n this.baseLogger.warn(`[CHAIN:${hash}] ${msg}`, redact(data));\n }\n\n error(msg: string, err?: any) {\n const secureErr = err instanceof SecureError ? err : new SecureError(err?.message || 'Error');\n const hash = this.chain(msg, secureErr.toJSON());\n this.baseLogger.error(`[CHAIN:${hash}] ${msg}`, redact(secureErr.toJSON()));\n }\n}\n\n/**\n * Convenience logger creator.\n */\nexport const createSecureLogger = (baseLogger: any) => new SecureLoggerChain(baseLogger);\n\n/**\n * Fastify Plugin Preset.\n * Fastify hooks to inject secure headers, rate limiter, and scan inputs.\n */\nexport const fastifyPlugin = (\n options: { rateLimit?: boolean; rateLimitWindowMs?: number; rateLimitMax?: number } = {},\n) => {\n const limiter = options.rateLimit\n ? new RateLimiter(\n options.rateLimitMax || 100,\n options.rateLimitWindowMs || 60000,\n new MemoryStore(options.rateLimitWindowMs || 60000),\n )\n : null;\n\n return async (fastify: any) => {\n fastify.addHook('onRequest', async (req: any, reply: any) => {\n Object.entries(headers.standardHeaders).forEach(([key, value]) => {\n reply.header(key, value);\n });\n\n if (limiter) {\n const ip = req.ip || 'unknown';\n if (await limiter.isLimited(ip)) {\n reply.code(429).send({ error: 'Too Many Requests' });\n return reply;\n }\n }\n });\n\n fastify.addHook('preHandler', async (req: any, reply: any) => {\n try {\n if (req.body && typeof req.body === 'object') {\n if (validate.scanForSecrets(req.body)) {\n throw new SecureError(\n 'Security Violation: Potential secret leakage detected.',\n 'BAD_INPUT',\n );\n }\n }\n } catch (err: any) {\n const secureErr =\n err instanceof SecureError ? err : new SecureError(err.message, 'BAD_INPUT');\n reply.code(400).send(secureErr.toJSON());\n return reply;\n }\n\n req.mitigator = {\n sanitize: (html: string) => sanitize.sanitizeHtml(html),\n safeJson: (text: string) => safeJson.parse(text),\n };\n });\n };\n};\n\n/**\n * NestJS Guard / Middleware class creator.\n * Dynamic NestJS Middleware to apply Mitigator protections.\n */\nexport class NestJsMitigatorMiddleware {\n private static limiter: RateLimiter | null = null;\n\n static configure(\n options: { rateLimit?: boolean; rateLimitWindowMs?: number; rateLimitMax?: number } = {},\n ) {\n if (options.rateLimit) {\n this.limiter = new RateLimiter(\n options.rateLimitMax || 100,\n options.rateLimitWindowMs || 60000,\n new MemoryStore(options.rateLimitWindowMs || 60000),\n );\n }\n }\n\n async use(req: any, res: any, next: () => void) {\n Object.entries(headers.standardHeaders).forEach(([key, value]) => {\n res.setHeader(key, value);\n });\n\n if (NestJsMitigatorMiddleware.limiter) {\n const ip = req.ip || req.connection?.remoteAddress || 'unknown';\n if (await NestJsMitigatorMiddleware.limiter.isLimited(ip)) {\n res.status(429).json({ error: 'Too Many Requests' });\n return;\n }\n }\n\n try {\n if (req.body && typeof req.body === 'object') {\n if (validate.scanForSecrets(req.body)) {\n throw new SecureError(\n 'Security Violation: Potential secret leakage detected.',\n 'BAD_INPUT',\n );\n }\n }\n } catch (err: any) {\n const secureErr =\n err instanceof SecureError ? err : new SecureError(err.message, 'BAD_INPUT');\n res.status(400).json(secureErr.toJSON());\n return;\n }\n\n req.mitigator = {\n sanitize: (html: string) => sanitize.sanitizeHtml(html),\n safeJson: (text: string) => safeJson.parse(text),\n };\n next();\n }\n}\n"],"mappings":"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","names":["Buffer","randomBytes","Buffer","randomBytes","createHash","timingSafeEqual","createHmac","resolve","Buffer","randomBytes","createHmac","createHash","timingSafeEqual","createHash","randomBytes","createHash","createHash","createHash"]}
package/package.json ADDED
@@ -0,0 +1,86 @@
1
+ {
2
+ "name": "mitigator",
3
+ "version": "1.0.0",
4
+ "description": "A production-grade, security-first TypeScript library for Node.js. Defends against XSS, Prototype Pollution, Path Traversal, SQL/NoSQL Injection, and more. Includes adaptive rate limiting, WebAuthn/Passkeys, AES-256-GCM sessions, and post-quantum cryptography (WOTS).",
5
+ "main": "./dist/index.cjs",
6
+ "module": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "require": "./dist/index.cjs"
13
+ }
14
+ },
15
+ "type": "module",
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "bin": {
20
+ "mitigator-audit": "dist/bin/mitigator-audit.js"
21
+ },
22
+ "engines": {
23
+ "node": ">=18.0.0"
24
+ },
25
+ "publishConfig": {
26
+ "access": "public"
27
+ },
28
+ "scripts": {
29
+ "build": "tsup",
30
+ "watch": "tsup --watch",
31
+ "prepublishOnly": "npm run build",
32
+ "test": "vitest run",
33
+ "test:watch": "vitest",
34
+ "test:coverage": "vitest run --coverage",
35
+ "lint": "eslint .",
36
+ "format": "prettier --write .",
37
+ "format:check": "prettier --check ."
38
+ },
39
+ "keywords": [
40
+ "security",
41
+ "xss",
42
+ "sanitize",
43
+ "rate-limit",
44
+ "csrf",
45
+ "jwt",
46
+ "webauthn",
47
+ "passkey",
48
+ "prototype-pollution",
49
+ "path-traversal",
50
+ "injection",
51
+ "crypto",
52
+ "aes-gcm",
53
+ "shamir-secret-sharing",
54
+ "post-quantum",
55
+ "wots",
56
+ "typescript",
57
+ "node"
58
+ ],
59
+ "repository": {
60
+ "type": "git",
61
+ "url": "git+https://github.com/MohamedSoliman21/mitigator.git"
62
+ },
63
+ "bugs": {
64
+ "url": "https://github.com/MohamedSoliman21/mitigator/issues"
65
+ },
66
+ "homepage": "https://github.com/MohamedSoliman21/mitigator#readme",
67
+ "author": "Mohamed Soliman",
68
+ "license": "ISC",
69
+ "devDependencies": {
70
+ "@eslint/js": "^9.16.0",
71
+ "@types/node": "^25.6.0",
72
+ "@types/sanitize-html": "^2.16.1",
73
+ "@vitest/coverage-v8": "^4.1.4",
74
+ "eslint": "^9.16.0",
75
+ "eslint-config-prettier": "^9.1.0",
76
+ "prettier": "^3.4.2",
77
+ "tslib": "^2.8.1",
78
+ "tsup": "^8.3.5",
79
+ "typescript": "^6.0.2",
80
+ "typescript-eslint": "^8.18.0",
81
+ "vitest": "^4.1.4"
82
+ },
83
+ "dependencies": {
84
+ "sanitize-html": "^2.17.4"
85
+ }
86
+ }