UNPKG

@arcjet/analyze

Version:

Arcjet local analysis engine

119 lines (116 loc) 4.3 kB
import { initializeWasm } from '@arcjet/analyze-wasm'; const FREE_EMAIL_PROVIDERS = [ "gmail.com", "yahoo.com", "hotmail.com", "aol.com", "hotmail.co.uk", ]; function noOpSensitiveInfoDetect() { return []; } function noOpBotsDetect() { return []; } function createCoreImports(detect) { if (typeof detect !== "function") { detect = noOpSensitiveInfoDetect; } return { "arcjet:js-req/bot-identifier": { detect: noOpBotsDetect, }, "arcjet:js-req/email-validator-overrides": { isFreeEmail(domain) { if (FREE_EMAIL_PROVIDERS.includes(domain)) { return "yes"; } return "unknown"; }, isDisposableEmail() { return "unknown"; }, hasMxRecords() { return "unknown"; }, hasGravatar() { return "unknown"; }, }, // TODO(@wooorm-arcjet): figure out a test case for this with the default `detect`. "arcjet:js-req/sensitive-information-identifier": { detect, }, // TODO(@wooorm-arcjet): figure out a test case for this that calls `verify`. "arcjet:js-req/verify-bot": { verify() { return "unverifiable"; }, }, }; } // TODO(@wooorm-arcjet): document what is used to fingerprint. /** * Generate a fingerprint for the client. This is used to identify the client * across multiple requests. * @param context - The Arcjet Analyze context. * @param request - The request to fingerprint. * @returns A SHA-256 string fingerprint. */ async function generateFingerprint(context, request) { const { log } = context; const coreImports = createCoreImports(); const analyze = await initializeWasm(coreImports); if (typeof analyze !== "undefined") { return analyze.generateFingerprint(JSON.stringify(request), context.characteristics); // Ignore the `else` branch as we test in places that have WebAssembly. /* node:coverage ignore next 4 */ } log.debug("WebAssembly is not supported in this runtime"); return ""; } // TODO(@wooorm-arcjet): docs. async function isValidEmail(context, candidate, options) { const { log } = context; const coreImports = createCoreImports(); const analyze = await initializeWasm(coreImports); if (typeof analyze !== "undefined") { return analyze.isValidEmail(candidate, options); // Ignore the `else` branch as we test in places that have WebAssembly. /* node:coverage ignore next 4 */ } log.debug("WebAssembly is not supported in this runtime"); return { blocked: [], validity: "valid" }; } // TODO(@wooorm-arcjet): docs. async function detectBot(context, request, options) { const { log } = context; const coreImports = createCoreImports(); const analyze = await initializeWasm(coreImports); if (typeof analyze !== "undefined") { return analyze.detectBot(JSON.stringify(request), options); // Ignore the `else` branch as we test in places that have WebAssembly. /* node:coverage ignore next 4 */ } log.debug("WebAssembly is not supported in this runtime"); return { allowed: [], denied: [], spoofed: false, verified: false }; } // TODO(@wooorm-arcjet): docs. async function detectSensitiveInfo(context, candidate, entities, contextWindowSize, detect) { const { log } = context; const coreImports = createCoreImports(detect); const analyze = await initializeWasm(coreImports); if (typeof analyze !== "undefined") { const skipCustomDetect = typeof detect !== "function"; return analyze.detectSensitiveInfo(candidate, { entities, contextWindowSize, skipCustomDetect, }); // Ignore the `else` branch as we test in places that have WebAssembly. /* node:coverage ignore next 4 */ } log.debug("WebAssembly is not supported in this runtime"); throw new Error("SENSITIVE_INFO rule failed to run because Wasm is not supported in this environment."); } export { detectBot, detectSensitiveInfo, generateFingerprint, isValidEmail };