@aikidosec/firewall
Version:
Zen by Aikido is an embedded Web Application Firewall that autonomously protects Node.js apps against common and critical attacks
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;
};
}