Skip to content

Commit a59b018

Browse files
committed
Fix root path disclosure
1 parent 54784b0 commit a59b018

File tree

4 files changed

+32
-5
lines changed

4 files changed

+32
-5
lines changed

HISTORY.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
unreleased
2+
==========
3+
4+
* Fix root path disclosure
5+
16
1.2.0 / 2015-01-05
27
==================
38

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ malicious:
4242
- The relative path is an absolute path
4343
- The relative path contains a NULL byte
4444
- The relative path resolves to a path outside of the root path
45+
- The relative path traverses above the root and back down
4546

4647
## Example
4748

index.js

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@ var sep = require('path').sep
2121

2222
module.exports = resolvePath
2323

24+
/**
25+
* Module variables.
26+
* @private
27+
*/
28+
29+
var upPathRegexp = /(?:^|[\\\/])\.\.(?:[\\\/]|$)/
30+
2431
/**
2532
* Resolve relative path against a root path
2633
*
@@ -65,16 +72,16 @@ function resolvePath(rootPath, relativePath) {
6572
throw createError(400, 'Malicious Path')
6673
}
6774

75+
// path outside root
76+
if (upPathRegexp.test(normalize('.' + sep + path))) {
77+
throw createError(403)
78+
}
79+
6880
// resolve & normalize the root path
6981
root = normalize(resolve(root) + sep)
7082

7183
// resolve the path
7284
path = resolve(root, path)
7385

74-
// path outside root
75-
if ((path + sep).substr(0, root.length) !== root) {
76-
throw createError(403)
77-
}
78-
7986
return path
8087
}

test/resolvePath.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,13 @@ describe('resolvePath(relativePath)', function () {
5757
expectError(403, 'Forbidden'))
5858
})
5959
})
60+
61+
describe('when relativePath discloses cwd', function () {
62+
it('should throw Forbidden error', function () {
63+
assert.throws(resolvePath.bind(null, join('test', '..', '..', basename(process.cwd()), 'index.js')),
64+
expectError(403, 'Forbidden'))
65+
})
66+
})
6067
})
6168

6269
describe('resolvePath(rootPath, relativePath)', function () {
@@ -139,6 +146,13 @@ describe('resolvePath(rootPath, relativePath)', function () {
139146
expectError(403, 'Forbidden'))
140147
})
141148
})
149+
150+
describe('when relativePath discloses rootPath', function () {
151+
it('should throw Forbidden error', function () {
152+
assert.throws(resolvePath.bind(null, __dirname, join('test', '..', '..', basename(__dirname), 'index.js')),
153+
expectError(403, 'Forbidden'))
154+
})
155+
})
142156
})
143157

144158
function expectError(status, message) {

0 commit comments

Comments
 (0)