@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.
75 lines (74 loc) • 3.11 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.cleanupStackTrace = cleanupStackTrace;
const escapeStringRegexp_1 = require("./escapeStringRegexp");
function cleanupStackTrace(stack, libraryRoot) {
try {
const newStackLines = stack
.split("\n")
.filter(createLineFilter(libraryRoot))
.map(createLineMapper(libraryRoot));
// If the stack only has one line (the error message), we return the original stack trace.
// This could happen if the detected library root is wrong
if (newStackLines.length <= 1) {
return stack;
}
return newStackLines.join("\n").trim();
}
catch {
// Safer to return the original stack trace in case of an error
// than to crash the application
return stack;
}
}
function createLineFilter(libraryRoot) {
const justACarrot = /^\^$/;
const pathRegexWithLineNumbers = new RegExp("^" + (0, escapeStringRegexp_1.escapeStringRegexp)(libraryRoot) + "\\S*(:\\d+){1,2}$");
return function lineFilter(line) {
if (line.includes("cleanupStackTrace") && line.includes("new Error")) {
return false;
}
// /Users/hansott/Code/my-project/server/node_modules/@aikidosec/firewall/agent/applyHooks.js:152
if (pathRegexWithLineNumbers.test(line.trimStart())) {
return false;
}
// Cleanup carrot under new Error().stack!
// stack: cleanupStackTrace(new Error().stack!, libraryRoot),
// ^
if (justACarrot.test(line.trimStart())) {
return false;
}
// Cleanup our own stack traces
// Examples:
// at Collection.wrap (/Code/runtime-node/build/agent/applyHooks.js:154:75)
// at /Code/runtime-node/build/sources/express/wrapRequestHandler.js:22:20
const parts = line.trimStart().split(" ");
if (parts.length > 1 && line.trimStart().startsWith("at ")) {
const lastPart = parts[parts.length - 1];
if (lastPart.startsWith("(") &&
lastPart.endsWith(")") &&
pathRegexWithLineNumbers.test(lastPart.slice(1, -1))) {
return false;
}
if (pathRegexWithLineNumbers.test(lastPart)) {
return false;
}
}
return true;
};
}
function createLineMapper(libraryRoot) {
const pathRegex = new RegExp((0, escapeStringRegexp_1.escapeStringRegexp)(libraryRoot) + "\\S*");
return function lineMapper(line) {
if (line.trimStart().startsWith("at ")) {
const parts = line.trimStart().split(" ");
if (parts.length === 4) {
// Cleanup our own stack traces
// Examples
// at Object.unifiedUsers (/Users/hansott/Code/my-project/server/src/GraphQL/Mutation.ts:4491:31) /Users/hansott/Code/my-project/server/node_modules/@aikidosec/firewall
return line.replace(pathRegex, "");
}
}
return line;
};
}