@aikidosec/firewall
Version:
Zen by Aikido is an embedded Web Application Firewall that autonomously protects Node.js apps against common and critical attacks
61 lines (60 loc) • 2.26 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildRouteFromURL = buildRouteFromURL;
const looksLikeASecret_1 = require("./looksLikeASecret");
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];
function buildRouteFromURL(url) {
const path = (0, tryParseURLPath_1.tryParseURLPath)(url);
if (!path) {
return undefined;
}
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 ((0, looksLikeASecret_1.looksLikeASecret)(segment)) {
return ":secret";
}
return segment;
}