UNPKG

@aikidosec/firewall

Version:

Zen by Aikido is an embedded Application Firewall that autonomously protects Node.js apps against common and critical attacks, provides rate limiting, detects malicious traffic (including bots), and more.

72 lines (71 loc) 2.66 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.buildRouteFromURL = buildRouteFromURL; const looksLikeASecret_1 = require("./looksLikeASecret"); const safeDecodeURIComponent_1 = require("./safeDecodeURIComponent"); const tryParseURLPath_1 = require("./tryParseURLPath"); const net_1 = require("net"); const UUID = /(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/i; const OBJECT_ID = /^[0-9a-f]{24}$/i; const ULID = /^[0-9A-HJKMNP-TV-Z]{26}$/i; const NUMBER = /^\d+$/; const DATE = /^\d{4}-\d{2}-\d{2}|\d{2}-\d{2}-\d{4}$/; const EMAIL = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/; const HASH = /^(?:[a-f0-9]{32}|[a-f0-9]{40}|[a-f0-9]{64}|[a-f0-9]{128})$/i; const HASH_LENGTHS = [32, 40, 64, 128]; const NUMBER_ARRAY = /^\d+(?:,\d+)*$/; function buildRouteFromURL(url) { let path = (0, tryParseURLPath_1.tryParseURLPath)(url); if (!path) { return undefined; } if (path.includes("%") && path.length >= 3) { const decoded = (0, safeDecodeURIComponent_1.safeDecodeURIComponent)(path); if (decoded) { path = decoded; } } const route = path.split("/").map(replaceURLSegmentWithParam).join("/"); if (route === "/") { return "/"; } if (route.endsWith("/")) { return route.slice(0, -1); } return route; } function replaceURLSegmentWithParam(segment) { const charCode = segment.charCodeAt(0); const startsWithNumber = charCode >= 48 && charCode <= 57; // ASCII codes for '0' to '9' if (startsWithNumber && NUMBER.test(segment)) { return ":number"; } if (segment.length === 36 && UUID.test(segment)) { return ":uuid"; } if (segment.length === 26 && ULID.test(segment)) { return ":ulid"; } if (segment.length === 24 && OBJECT_ID.test(segment)) { return ":objectId"; } if (startsWithNumber && DATE.test(segment)) { return ":date"; } if (segment.includes("@") && EMAIL.test(segment)) { return ":email"; } if ((segment.includes(":") || segment.includes(".")) && (0, net_1.isIP)(segment)) { return ":ip"; } if (HASH_LENGTHS.includes(segment.length) && HASH.test(segment)) { return ":hash"; } if (startsWithNumber && NUMBER_ARRAY.test(segment)) { return ":array(number)"; } if ((0, looksLikeASecret_1.looksLikeASecret)(segment)) { return ":secret"; } return segment; }