/src/handler.js |
@@ -12,14 +12,10 @@ |
|
// Checks whether userPath is a child of rootPath. |
function isRooted(userPath, rootPath, separator, callback) { |
fs.realpath(userPath, (error, resolved) => { |
if (error) |
return false; |
resolved = resolved.split(separator).filter(Boolean); |
userPath = userPath.split(separator).filter(Boolean); |
rootPath = rootPath.split(separator).filter(Boolean); |
callback(resolved.length >= rootPath.length && |
rootPath.every((e, i) => e === resolved[i])); |
}); |
callback(userPath.length >= rootPath.length && |
rootPath.every((e, i) => e === userPath[i])); |
} |
|
// Serves files. |
@@ -182,9 +178,22 @@ |
path.join(root, trimmedPath) : |
path.resolve(root, trimmedPath); |
|
fs.realpath(requestPath, (error, resolvedPath) => { |
if (error) { |
callback('Unknown path requested: ' + |
requestAddress.address + ':' + |
requestAddress.port + |
' requesting: ' + |
requestURL.pathname, |
module.exports.error.level.WARN |
); |
response.statusCode = 404; |
response.end(); |
return; |
} |
// Check for path traversals early on and bail if the requested path does not |
// lie within the specified document root. |
isRooted(requestPath, root, path.sep, (rooted) => { |
isRooted(resolvedPath, root, path.sep, (rooted) => { |
if (!rooted) { |
process.nextTick(() => { |
callback('Attempted path traversal: ' + |
@@ -252,5 +261,6 @@ |
); |
}); |
}); |
}); |
} |
}; |