node-http-server – Diff between revs 22 and 23
?pathlinks?
Rev 22 | Rev 23 | |||
---|---|---|---|---|
Line 10... | Line 10... | |||
10 | const mime = require('mime'); |
10 | const mime = require('mime'); |
|
11 | const auth = require("http-auth"); |
11 | const auth = require("http-auth"); |
|
Line 12... | Line 12... | |||
12 | |
12 | |
|
13 | // Checks whether userPath is a child of rootPath. |
13 | // Checks whether userPath is a child of rootPath. |
|
- | 14 | function isRooted(userPath, rootPath, separator, callback) { |
||
- | 15 | fs.realpath(userPath, (error, resolved) => { |
||
14 | function isRooted(userPath, rootPath, separator, callback) { |
16 | if (error) |
|
15 | process.nextTick(() => { |
17 | return false; |
|
16 | userPath = userPath.split(separator).filter(Boolean); |
18 | resolved = resolved.split(separator).filter(Boolean); |
|
17 | rootPath = rootPath.split(separator).filter(Boolean); |
19 | rootPath = rootPath.split(separator).filter(Boolean); |
|
18 | callback(userPath.length >= rootPath.length && |
20 | callback(resolved.length >= rootPath.length && |
|
19 | rootPath.every((e, i) => e === userPath[i])); |
21 | rootPath.every((e, i) => e === resolved[i])); |
|
20 | }); |
22 | }); |
|
Line 21... | Line 23... | |||
21 | } |
23 | } |
|
22 | |
24 | |
|
Line 138... | Line 140... | |||
138 | index(config, request, response, requestPath, requestURL, callback); |
140 | index(config, request, response, requestPath, requestURL, callback); |
|
139 | return; |
141 | return; |
|
140 | } |
142 | } |
|
141 | if (stats.isFile()) { |
143 | if (stats.isFile()) { |
|
142 | const file = path.parse(requestPath).base; |
144 | const file = path.parse(requestPath).base; |
|
143 | |
145 | |
|
144 | // If the file matches the reject list or is not in the accept list, |
146 | // If the file matches the reject list or is not in the accept list, |
|
145 | // then there is no file to serve. |
147 | // then there is no file to serve. |
|
146 | if (config.site.reject.some((expression) => expression.test(file)) || |
148 | if (config.site.reject.some((expression) => expression.test(file)) || |
|
147 | !config.site.accept.some((expression) => expression.test(file))) { |
149 | !config.site.accept.some((expression) => expression.test(file))) { |
|
148 | response.statusCode = 404; |
150 | response.statusCode = 404; |
|
Line 178... | Line 180... | |||
178 | .join('/'); |
180 | .join('/'); |
|
179 | const requestPath = trimmedPath === '/' ? |
181 | const requestPath = trimmedPath === '/' ? |
|
180 | path.join(root, trimmedPath) : |
182 | path.join(root, trimmedPath) : |
|
181 | path.resolve(root, trimmedPath); |
183 | path.resolve(root, trimmedPath); |
|
Line -... | Line 184... | |||
- | 184 | |
||
- | 185 | // Check for path traversals early on and bail if the requested path does not |
||
182 | |
186 | // lie within the specified document root. |
|
183 | isRooted(requestPath, root, path.sep, (rooted) => { |
187 | isRooted(requestPath, root, path.sep, (rooted) => { |
|
184 | if (!rooted) { |
188 | if (!rooted) { |
|
185 | process.nextTick(() => { |
189 | process.nextTick(() => { |
|
186 | callback('Attempted path traversal: ' + |
190 | callback('Attempted path traversal: ' + |