Skip to content

Commit 0399e39

Browse files
committed
Fix potential open redirect when mounted at root
fixes #26
1 parent 1d063cc commit 0399e39

File tree

3 files changed

+33
-2
lines changed

3 files changed

+33
-2
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 potential open redirect when mounted at root
5+
16
1.7.1 / 2014-10-22
27
==================
38

index.js

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,13 @@ exports = module.exports = function serveStatic(root, options) {
7979
return next()
8080
}
8181

82-
originalUrl.pathname += '/'
82+
// append trailing slash
83+
originalUrl.pathname = collapseLeadingSlashes(originalUrl.pathname + '/')
8384

85+
// reformat the URL
8486
var target = url.format(originalUrl)
8587

88+
// send redirect response
8689
res.statusCode = 303
8790
res.setHeader('Content-Type', 'text/html; charset=utf-8')
8891
res.setHeader('Location', target)
@@ -116,3 +119,19 @@ exports = module.exports = function serveStatic(root, options) {
116119
*/
117120

118121
exports.mime = send.mime
122+
123+
/**
124+
* Collapse all leading slashes into a single slash
125+
* @private
126+
*/
127+
function collapseLeadingSlashes(str) {
128+
for (var i = 0; i < str.length; i++) {
129+
if (str[i] !== '/') {
130+
break
131+
}
132+
}
133+
134+
return i > 1
135+
? '/' + str.substr(i)
136+
: str
137+
}

test/test.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,13 @@ describe('serveStatic()', function(){
259259
.expect(303, done)
260260
})
261261

262+
it('should not redirect to protocol-relative locations', function (done) {
263+
request(server)
264+
.get('//users')
265+
.expect('Location', '/users/')
266+
.expect(303, done)
267+
})
268+
262269
it('should not redirect incorrectly', function (done) {
263270
request(server)
264271
.get('/')
@@ -532,7 +539,7 @@ describe('serveStatic()', function(){
532539
it('should not choke on auth-looking URL', function(done){
533540
request(server)
534541
.get('//todo@txt')
535-
.expect('Location', '//todo@txt/')
542+
.expect('Location', '/todo@txt/')
536543
.expect(303, done);
537544
});
538545
});

0 commit comments

Comments
 (0)