How to prevent directory traversal when joining paths in node.js?
Here's is one approach I've used in this situation:
path.normalize()
handles all.
and..
, so you can be sure that if either one is present, it will be at the front of the path.- Remove any
../../
from the front of your path.
So:
var safeSuffix = path.normalize(unsafeSuffix).replace(/^(\.\.(\/|\\|$))+/, '');
var safeJoin = path.join(basePath, safeSuffix);
About your approach: checking the prefix seems like a pretty good idea to me. There are a couple of problems I see with your implementation:
- You've checked for a prefix without a trailing slash:
../html-other
will resolve topublic/html-other
, which I guess is not what you want. - You would run into trouble on Windows systems, where
.normalize()
would convert/
to\
, meaning no paths would work.
When I've done prefix-checking (for slightly different situations), here's what I ended up with:
function checkPrefix(prefix, candidate) {
// .resolve() removes trailing slashes
var absPrefix = path.resolve(prefix) + path.sep;
var absCandidate = path.resolve(candidate) + path.sep;
return absCandidate.substring(0, absPrefix.length) === absPrefix;
}
(Yes, I added path.sep
to both, so that the prefix dir itself passes the test.)