I am writing an (expressjs) http service, which gets a relative path as user input on every call, reads a file from the filesystem based on that path, and processes it, like:
app.get("/api", (req, res, next) => {
var filePath = path.resolve("./datasource", req.query.path);
fs.readFile(filePath, "utf8", (err, data) => {
processData(data, (err, processed) => {
res.json(processed);
});
});
});
I stripped out error handling for clarity. The problem with this is that one could call the url /api?path=../../../etc/passwd, and that would leak information from the server itself. I would like this api not to process files outside of the ./datasource folder. I think I could use some customized implementation of path.resolve, which does not escape the parent, but it looks like to me there is no such functionality in the path module. Some examples I thought of:
saferesolve("./datasource", "a/b") === "./datasource/a/b"
saferesolve("./datasource", "a/b/../c") === "./datasource/a/c"
saferesolve("./datasource", "../..") === "./datasource"
saferesolve("./datasource", "../../a/b") === "./datasource/a/b"
saferesolve("./datasource", "../../a/b/..") === "./datasource/a"
Any ideas how to accomplish this without reinventing the whole path module?
This seems to pass your tests:
function saferesolve(base, target) {
var targetPath = '.' + path.posix.normalize('/' + target)
return path.posix.resolve(base, targetPath)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With