Skip to content

Commit cecb6c7

Browse files
committed
add model for live-server
1 parent b509627 commit cecb6c7

File tree

5 files changed

+104
-0
lines changed

5 files changed

+104
-0
lines changed

javascript/ql/lib/semmle/javascript/frameworks/HttpFrameworks.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import semmle.javascript.frameworks.Express
22
import semmle.javascript.frameworks.Hapi
33
import semmle.javascript.frameworks.Koa
4+
import semmle.javascript.frameworks.LiveServer
45
import semmle.javascript.frameworks.NodeJSLib
56
import semmle.javascript.frameworks.Micro
67
import semmle.javascript.frameworks.Restify
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/**
2+
* Provides classes modelling the [live-server](https://npmjs.com/package/live-server) package.
3+
*/
4+
5+
import javascript
6+
private import semmle.javascript.frameworks.ConnectExpressShared::ConnectExpressShared as ConnectExpressShared
7+
8+
private module LiveServer {
9+
/**
10+
* An expression that imports the live-server package, seen as a server-definition.
11+
*/
12+
class ServerDefinition extends HTTP::Servers::StandardServerDefinition {
13+
API::Node imp;
14+
15+
ServerDefinition() {
16+
imp = API::moduleImport("live-server") and
17+
this = imp.getAnImmediateUse().asExpr()
18+
}
19+
20+
API::Node getImportNode() { result = imp }
21+
}
22+
23+
/**
24+
* A live-server middleware definition.
25+
* `live-server` uses the `connect` library under the hood, so the model is based on the `connect` model.
26+
*/
27+
class RouteHandler extends Connect::RouteHandler, DataFlow::FunctionNode {
28+
RouteHandler() { this = any(RouteSetup setup).getARouteHandler() }
29+
30+
override Parameter getRouteHandlerParameter(string kind) {
31+
result = ConnectExpressShared::getRouteHandlerParameter(astNode, kind)
32+
}
33+
}
34+
35+
/**
36+
* The call to `require("live-server").start()`, seen as a route setup.
37+
*/
38+
class RouteSetup extends MethodCallExpr, HTTP::Servers::StandardRouteSetup {
39+
ServerDefinition server;
40+
API::CallNode call;
41+
42+
RouteSetup() {
43+
call = server.getImportNode().getMember("start").getACall() and
44+
this = call.asExpr()
45+
}
46+
47+
override DataFlow::SourceNode getARouteHandler() {
48+
exists(DataFlow::SourceNode middleware |
49+
middleware = call.getParameter(0).getMember("middleware").getAValueReachingRhs()
50+
|
51+
result = middleware.getAMemberCall(["push", "unshift"]).getArgument(0).getAFunctionValue()
52+
or
53+
result = middleware.(DataFlow::ArrayCreationNode).getAnElement().getAFunctionValue()
54+
)
55+
}
56+
57+
override Expr getServer() { result = server }
58+
}
59+
}

javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/ReflectedXss.expected

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,18 @@ nodes
118118
| formatting.js:7:14:7:53 | require ... , evil) |
119119
| formatting.js:7:14:7:53 | require ... , evil) |
120120
| formatting.js:7:49:7:52 | evil |
121+
| live-server.js:4:11:4:27 | tainted |
122+
| live-server.js:4:21:4:27 | req.url |
123+
| live-server.js:4:21:4:27 | req.url |
124+
| live-server.js:6:13:6:50 | `<html> ... /html>` |
125+
| live-server.js:6:13:6:50 | `<html> ... /html>` |
126+
| live-server.js:6:28:6:34 | tainted |
127+
| live-server.js:10:11:10:27 | tainted |
128+
| live-server.js:10:21:10:27 | req.url |
129+
| live-server.js:10:21:10:27 | req.url |
130+
| live-server.js:12:13:12:50 | `<html> ... /html>` |
131+
| live-server.js:12:13:12:50 | `<html> ... /html>` |
132+
| live-server.js:12:28:12:34 | tainted |
121133
| pages/Next.jsx:8:13:8:19 | req.url |
122134
| pages/Next.jsx:8:13:8:19 | req.url |
123135
| pages/Next.jsx:8:13:8:19 | req.url |
@@ -325,6 +337,16 @@ edges
325337
| formatting.js:6:43:6:46 | evil | formatting.js:6:14:6:47 | util.fo ... , evil) |
326338
| formatting.js:7:49:7:52 | evil | formatting.js:7:14:7:53 | require ... , evil) |
327339
| formatting.js:7:49:7:52 | evil | formatting.js:7:14:7:53 | require ... , evil) |
340+
| live-server.js:4:11:4:27 | tainted | live-server.js:6:28:6:34 | tainted |
341+
| live-server.js:4:21:4:27 | req.url | live-server.js:4:11:4:27 | tainted |
342+
| live-server.js:4:21:4:27 | req.url | live-server.js:4:11:4:27 | tainted |
343+
| live-server.js:6:28:6:34 | tainted | live-server.js:6:13:6:50 | `<html> ... /html>` |
344+
| live-server.js:6:28:6:34 | tainted | live-server.js:6:13:6:50 | `<html> ... /html>` |
345+
| live-server.js:10:11:10:27 | tainted | live-server.js:12:28:12:34 | tainted |
346+
| live-server.js:10:21:10:27 | req.url | live-server.js:10:11:10:27 | tainted |
347+
| live-server.js:10:21:10:27 | req.url | live-server.js:10:11:10:27 | tainted |
348+
| live-server.js:12:28:12:34 | tainted | live-server.js:12:13:12:50 | `<html> ... /html>` |
349+
| live-server.js:12:28:12:34 | tainted | live-server.js:12:13:12:50 | `<html> ... /html>` |
328350
| pages/Next.jsx:8:13:8:19 | req.url | pages/Next.jsx:8:13:8:19 | req.url |
329351
| pages/Next.jsx:15:13:15:19 | req.url | pages/Next.jsx:15:13:15:19 | req.url |
330352
| pages/api/myapi.js:2:14:2:20 | req.url | pages/api/myapi.js:2:14:2:20 | req.url |
@@ -442,6 +464,8 @@ edges
442464
| etherpad.js:11:12:11:19 | response | etherpad.js:9:16:9:30 | req.query.jsonp | etherpad.js:11:12:11:19 | response | Cross-site scripting vulnerability due to $@. | etherpad.js:9:16:9:30 | req.query.jsonp | user-provided value |
443465
| formatting.js:6:14:6:47 | util.fo ... , evil) | formatting.js:4:16:4:29 | req.query.evil | formatting.js:6:14:6:47 | util.fo ... , evil) | Cross-site scripting vulnerability due to $@. | formatting.js:4:16:4:29 | req.query.evil | user-provided value |
444466
| formatting.js:7:14:7:53 | require ... , evil) | formatting.js:4:16:4:29 | req.query.evil | formatting.js:7:14:7:53 | require ... , evil) | Cross-site scripting vulnerability due to $@. | formatting.js:4:16:4:29 | req.query.evil | user-provided value |
467+
| live-server.js:6:13:6:50 | `<html> ... /html>` | live-server.js:4:21:4:27 | req.url | live-server.js:6:13:6:50 | `<html> ... /html>` | Cross-site scripting vulnerability due to $@. | live-server.js:4:21:4:27 | req.url | user-provided value |
468+
| live-server.js:12:13:12:50 | `<html> ... /html>` | live-server.js:10:21:10:27 | req.url | live-server.js:12:13:12:50 | `<html> ... /html>` | Cross-site scripting vulnerability due to $@. | live-server.js:10:21:10:27 | req.url | user-provided value |
445469
| pages/Next.jsx:8:13:8:19 | req.url | pages/Next.jsx:8:13:8:19 | req.url | pages/Next.jsx:8:13:8:19 | req.url | Cross-site scripting vulnerability due to $@. | pages/Next.jsx:8:13:8:19 | req.url | user-provided value |
446470
| pages/Next.jsx:15:13:15:19 | req.url | pages/Next.jsx:15:13:15:19 | req.url | pages/Next.jsx:15:13:15:19 | req.url | Cross-site scripting vulnerability due to $@. | pages/Next.jsx:15:13:15:19 | req.url | user-provided value |
447471
| pages/api/myapi.js:2:14:2:20 | req.url | pages/api/myapi.js:2:14:2:20 | req.url | pages/api/myapi.js:2:14:2:20 | req.url | Cross-site scripting vulnerability due to $@. | pages/api/myapi.js:2:14:2:20 | req.url | user-provided value |

javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/ReflectedXssWithCustomSanitizer.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
| ReflectedXssGood3.js:139:12:139:27 | escapeHtml3(url) | Cross-site scripting vulnerability due to $@. | ReflectedXssGood3.js:135:15:135:27 | req.params.id | user-provided value |
2626
| formatting.js:6:14:6:47 | util.fo ... , evil) | Cross-site scripting vulnerability due to $@. | formatting.js:4:16:4:29 | req.query.evil | user-provided value |
2727
| formatting.js:7:14:7:53 | require ... , evil) | Cross-site scripting vulnerability due to $@. | formatting.js:4:16:4:29 | req.query.evil | user-provided value |
28+
| live-server.js:6:13:6:50 | `<html> ... /html>` | Cross-site scripting vulnerability due to $@. | live-server.js:4:21:4:27 | req.url | user-provided value |
29+
| live-server.js:12:13:12:50 | `<html> ... /html>` | Cross-site scripting vulnerability due to $@. | live-server.js:10:21:10:27 | req.url | user-provided value |
2830
| pages/Next.jsx:8:13:8:19 | req.url | Cross-site scripting vulnerability due to $@. | pages/Next.jsx:8:13:8:19 | req.url | user-provided value |
2931
| pages/Next.jsx:15:13:15:19 | req.url | Cross-site scripting vulnerability due to $@. | pages/Next.jsx:15:13:15:19 | req.url | user-provided value |
3032
| pages/api/myapi.js:2:14:2:20 | req.url | Cross-site scripting vulnerability due to $@. | pages/api/myapi.js:2:14:2:20 | req.url | user-provided value |
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
var liveServer = require("live-server");
2+
3+
const middleware = [function(req, res, next) {
4+
const tainted = req.url;
5+
6+
res.end(`<html><body>${tainted}</body></html>`); // NOT OK
7+
}];
8+
9+
middleware.push(function(req, res, next) {
10+
const tainted = req.url;
11+
12+
res.end(`<html><body>${tainted}</body></html>`); // NOT OK
13+
});
14+
15+
var params = {
16+
middleware
17+
};
18+
liveServer.start(params);

0 commit comments

Comments
 (0)