@aikidosec/firewall
Version:
Zen by Aikido is an embedded Web Application Firewall that autonomously protects Node.js apps against common and critical attacks
66 lines (65 loc) • 2.79 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.detectPathTraversal = detectPathTraversal;
const containsUnsafePathParts_1 = require("./containsUnsafePathParts");
const unsafePathStart_1 = require("./unsafePathStart");
const url_1 = require("url");
function detectPathTraversal(filePath, userInput, checkPathStart = true, isUrl = false) {
if (userInput.length <= 1) {
// We ignore single characters since they don't pose a big threat.
return false;
}
// Check for URL path traversal
// Reason: new URL("file:///../../test.txt") => /test.txt
// The normal check for relative path traversal will fail in this case, because transformed path does not contain ../.
// For absolute path traversal, we dont need to check the transformed path, because it will always start with /.
// Also /./ is checked by normal absolute path traversal check (if #219 is merged)
// Use containsUnsafePathPartsUrl, because urls can contain a TAB, carriage return or line feed that is silently removed by the URL constructor.
if (isUrl && (0, containsUnsafePathParts_1.containsUnsafePathPartsUrl)(userInput)) {
const filePathFromUrl = parseAsFileUrl(userInput);
if (filePathFromUrl && filePath.includes(filePathFromUrl)) {
return true;
}
}
if (userInput.length > filePath.length) {
// We ignore cases where the user input is longer than the file path.
// Because the user input can't be part of the file path.
return false;
}
if (!filePath.includes(userInput)) {
// We ignore cases where the user input is not part of the file path.
return false;
}
if ((0, containsUnsafePathParts_1.containsUnsafePathParts)(filePath) && (0, containsUnsafePathParts_1.containsUnsafePathParts)(userInput)) {
return true;
}
if (checkPathStart) {
// Check for absolute path traversal
return (0, unsafePathStart_1.startsWithUnsafePath)(filePath, userInput);
}
return false;
}
/**
* This function is used to convert a file path as a URL to a file path.
* It is used to handle cases where a URL object is passed to a fs function.
* For example new URL("file:///../../test.txt") => file:///test.txt
* This function will convert ../../test.txt to /test.txt
* If the URL is not a file URL, it will return undefined.
* Another sample: new URL("file:///./test.txt") => /test.txt
*/
function parseAsFileUrl(path) {
let url = path;
if (!url.toLowerCase().startsWith("file:")) {
if (!url.startsWith("/")) {
url = `/${url}`;
}
url = `file://${url}`;
}
try {
return (0, url_1.fileURLToPath)(url);
}
catch {
//
}
return undefined;
}