Skip to content

Commit 4795b87

Browse files
committed
JS: Add model of Micro
1 parent 230f78a commit 4795b87

3 files changed

Lines changed: 136 additions & 0 deletions

File tree

javascript/ql/src/semmle/javascript/Promises.qll

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,23 @@ module Bluebird {
576576

577577
override DataFlow::Node getArrayNode() { result = getArgument(0) }
578578
}
579+
580+
/**
581+
* An async function created using a call to `bluebird.coroutine`.
582+
*/
583+
class BluebirdCoroutineDefinition extends DataFlow::CallNode {
584+
BluebirdCoroutineDefinition() {
585+
this = bluebird().getAMemberCall("coroutine")
586+
}
587+
}
588+
589+
private class BluebirdCoroutineDefinitionAsPartialInvoke extends DataFlow::PartialInvokeNode::Range, BluebirdCoroutineDefinition {
590+
override DataFlow::SourceNode getBoundFunction(DataFlow::Node callback, int boundArgs) {
591+
boundArgs = 0 and
592+
callback = getArgument(0) and
593+
result = this
594+
}
595+
}
579596
}
580597

581598
/**

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import semmle.javascript.frameworks.Express
22
import semmle.javascript.frameworks.Hapi
33
import semmle.javascript.frameworks.Koa
44
import semmle.javascript.frameworks.NodeJSLib
5+
import semmle.javascript.frameworks.Micro
56
import semmle.javascript.frameworks.Restify
67
import semmle.javascript.frameworks.Connect
78
import semmle.javascript.frameworks.Fastify
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/**
2+
* Provides a model of the `micro` NPM package.
3+
*/
4+
5+
private import javascript
6+
7+
private module Micro {
8+
private import DataFlow
9+
10+
/**
11+
* A node that should be interpreted as a route handler, to use as starting
12+
* point for back-tracking.
13+
*/
14+
Node microRouteHandlerSink() {
15+
result = moduleMember("micro", "run").getACall().getLastArgument()
16+
or
17+
result = moduleImport("micro").getACall().getArgument(0)
18+
}
19+
20+
/** Gets a data flow node referring to a thing. */
21+
private DataFlow::SourceNode microRouteHandler(DataFlow::TypeBackTracker t) {
22+
t.start() and
23+
result = microRouteHandlerSink().getALocalSource()
24+
or
25+
exists(DataFlow::TypeBackTracker t2 | result = microRouteHandler(t2).backtrack(t2, t))
26+
or
27+
exists(DataFlow::CallNode transformer |
28+
transformer = moduleImport("micro-compress").getACall()
29+
or
30+
transformer instanceof Bluebird::BluebirdCoroutineDefinition
31+
|
32+
microRouteHandler(t.continue()) = transformer and
33+
result = transformer.getArgument(0).getALocalSource()
34+
)
35+
}
36+
37+
/** Gets a data flow node referring to a thing. */
38+
DataFlow::SourceNode microRouteHandler() {
39+
result = microRouteHandler(DataFlow::TypeBackTracker::end())
40+
}
41+
42+
/**
43+
* A function passed to `micro` or `micro.run`.
44+
*/
45+
class MicroRouteHandler extends HTTP::Servers::StandardRouteHandler, DataFlow::FunctionNode {
46+
MicroRouteHandler() { this = microRouteHandler().getAFunctionValue() }
47+
}
48+
49+
class MicroRequestSource extends HTTP::Servers::RequestSource {
50+
MicroRouteHandler h;
51+
52+
MicroRequestSource() { this = h.getParameter(0) }
53+
54+
override HTTP::RouteHandler getRouteHandler() { result = h }
55+
}
56+
57+
class MicroResponseSource extends HTTP::Servers::ResponseSource {
58+
MicroRouteHandler h;
59+
60+
MicroResponseSource() { this = h.getParameter(1) }
61+
62+
override HTTP::RouteHandler getRouteHandler() { result = h }
63+
}
64+
65+
class MicroRequestExpr extends NodeJSLib::RequestExpr {
66+
override MicroRequestSource src;
67+
}
68+
69+
class MicroReseponseExpr extends NodeJSLib::ResponseExpr {
70+
override MicroResponseSource src;
71+
}
72+
73+
private HTTP::RouteHandler getRouteHandlerFromReqRes(DataFlow::Node node) {
74+
exists(HTTP::Servers::RequestSource src |
75+
src.ref().flowsTo(node) and
76+
result = src.getRouteHandler()
77+
)
78+
or
79+
exists(HTTP::Servers::ResponseSource src |
80+
src.ref().flowsTo(node) and
81+
result = src.getRouteHandler()
82+
)
83+
}
84+
85+
class MicroBodyParserCall extends HTTP::RequestInputAccess, DataFlow::CallNode {
86+
string name;
87+
88+
MicroBodyParserCall() {
89+
name = ["buffer", "text", "json"] and
90+
this = moduleMember("micro", name).getACall()
91+
}
92+
93+
override string getKind() {
94+
result = "body"
95+
}
96+
97+
override HTTP::RouteHandler getRouteHandler() {
98+
result = getRouteHandlerFromReqRes(getArgument(0))
99+
}
100+
101+
override predicate isUserControlledObject() {
102+
name = "json"
103+
}
104+
}
105+
106+
class MicroSendArgument extends HTTP::ResponseSendArgument {
107+
CallNode send;
108+
109+
MicroSendArgument() {
110+
send = moduleMember("micro", ["send", "sendError"]).getACall() and
111+
this = send.getLastArgument().asExpr()
112+
}
113+
114+
override HTTP::RouteHandler getRouteHandler() {
115+
result = getRouteHandlerFromReqRes(send.getArgument([0, 1]))
116+
}
117+
}
118+
}

0 commit comments

Comments
 (0)