Skip to content

Commit 32859eb

Browse files
committed
move to experimental
1 parent 4198f61 commit 32859eb

File tree

11 files changed

+223
-163
lines changed

11 files changed

+223
-163
lines changed

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

Lines changed: 39 additions & 155 deletions
Original file line numberDiff line numberDiff line change
@@ -3,177 +3,61 @@
33
*/
44

55
import javascript
6-
import semmle.javascript.frameworks.ReadableStream
76

87
/**
9-
* A module for modeling [busboy](https://www.npmjs.com/package/busboy) package
8+
* A source of remote flow from the `Busboy` library.
109
*/
11-
module BusBoy {
12-
/**
13-
* A source of remote flow from the `Busboy` library.
14-
*/
15-
private class BusBoyRemoteFlow extends RemoteFlowSource {
16-
BusBoyRemoteFlow() {
17-
exists(API::Node busboyOnEvent |
18-
busboyOnEvent = API::moduleImport("busboy").getReturn().getMember("on")
19-
|
20-
// Files
21-
busboyOnEvent.getParameter(0).asSink().mayHaveStringValue("file") and
22-
// second param of 'file' event is a Readable stream
23-
this = readableStreamDataNode(busboyOnEvent.getParameter(1).getParameter(1))
24-
or
25-
// Fields
26-
busboyOnEvent.getParameter(0).asSink().mayHaveStringValue(["file", "field"]) and
27-
this =
28-
API::moduleImport("busboy")
29-
.getReturn()
30-
.getMember("on")
31-
.getParameter(1)
32-
.getAParameter()
33-
.asSource()
34-
)
35-
}
36-
37-
override string getSourceType() { result = "parsed user value from Busbuy" }
10+
private class BusBoyRemoteFlow extends RemoteFlowSource {
11+
BusBoyRemoteFlow() {
12+
this =
13+
API::moduleImport("busboy")
14+
.getInstance()
15+
.getMember("on")
16+
.getParameter(1)
17+
.getAParameter()
18+
.asSource()
3819
}
3920

40-
/**
41-
* A busboy file data step according to a Readable Stream type
42-
*/
43-
private class AdditionalTaintStep extends TaintTracking::SharedTaintStep {
44-
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
45-
exists(API::Node busboyOnEvent |
46-
busboyOnEvent = API::moduleImport("busboy").getReturn().getMember("on")
47-
|
48-
busboyOnEvent.getParameter(0).asSink().mayHaveStringValue("file") and
49-
customStreamPipeAdditionalTaintStep(busboyOnEvent.getParameter(1).getParameter(1), pred,
50-
succ)
51-
)
52-
}
53-
}
21+
override string getSourceType() { result = "parsed user value from Busbuy" }
5422
}
5523

5624
/**
57-
* A module for modeling [formidable](https://www.npmjs.com/package/formidable) package
25+
* A source of remote flow from the `Formidable` library parsing a HTTP request.
5826
*/
59-
module Formidable {
60-
/**
61-
* A source of remote flow from the `Formidable` library parsing a HTTP request.
62-
*/
63-
private class FormidableRemoteFlow extends RemoteFlowSource {
64-
FormidableRemoteFlow() {
65-
exists(API::Node formidable |
66-
formidable = API::moduleImport("formidable").getReturn()
67-
or
68-
formidable = API::moduleImport("formidable").getMember("formidable").getReturn()
69-
or
70-
formidable =
71-
API::moduleImport("formidable").getMember(["IncomingForm", "Formidable"]).getInstance()
72-
|
73-
this =
74-
formidable.getMember("parse").getACall().getABoundCallbackParameter(1, any(int i | i > 0))
75-
or
76-
// if callback is not provide a promise will be returned,
77-
// return values contains [fields,files] members
78-
exists(API::Node parseMethod |
79-
parseMethod = formidable.getMember("parse") and parseMethod.getNumParameter() = 1
80-
|
81-
this = parseMethod.getReturn().asSource()
82-
)
83-
or
84-
// event handler
85-
this = formidable.getMember("on").getParameter(1).getAParameter().asSource()
86-
)
87-
}
88-
89-
override string getSourceType() { result = "parsed user value from Formidable" }
27+
private class FormidableRemoteFlow extends RemoteFlowSource {
28+
FormidableRemoteFlow() {
29+
exists(API::Node formidable |
30+
formidable = API::moduleImport("formidable").getReturn()
31+
or
32+
formidable = API::moduleImport("formidable").getMember("formidable").getReturn()
33+
or
34+
formidable =
35+
API::moduleImport("formidable").getMember(["IncomingForm", "Formidable"]).getInstance()
36+
|
37+
this =
38+
formidable.getMember("parse").getACall().getABoundCallbackParameter(1, any(int i | i > 0))
39+
)
9040
}
91-
}
9241

93-
/**
94-
* A module for modeling [multiparty](https://www.npmjs.com/package/multiparty) package
95-
*/
96-
module Multiparty {
97-
/**
98-
* A source of remote flow from the `Multiparty` library.
99-
*/
100-
private class MultipartyRemoteFlow extends RemoteFlowSource {
101-
MultipartyRemoteFlow() {
102-
exists(API::Node form |
103-
form = API::moduleImport("multiparty").getMember("Form").getInstance()
104-
|
105-
exists(API::CallNode parse | parse = form.getMember("parse").getACall() |
106-
this = parse.getParameter(1).getParameter([1, 2]).asSource()
107-
)
108-
or
109-
exists(API::Node on | on = form.getMember("on") |
110-
(
111-
on.getParameter(0).asSink().mayHaveStringValue(["file", "field"]) and
112-
this = on.getParameter(1).getParameter([0, 1]).asSource()
113-
or
114-
on.getParameter(0).asSink().mayHaveStringValue("part") and
115-
this = readableStreamDataNode(on.getParameter(1).getParameter(0))
116-
)
117-
)
118-
)
119-
}
120-
121-
override string getSourceType() { result = "parsed user value from Multiparty" }
122-
}
123-
124-
/**
125-
* A multiparty part data step according to a Readable Stream type
126-
*/
127-
private class AdditionalTaintStep extends TaintTracking::SharedTaintStep {
128-
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
129-
exists(API::Node multipartyOnEvent |
130-
multipartyOnEvent =
131-
API::moduleImport("multiparty").getMember("Form").getInstance().getMember("on")
132-
|
133-
multipartyOnEvent.getParameter(0).asSink().mayHaveStringValue("part") and
134-
customStreamPipeAdditionalTaintStep(multipartyOnEvent.getParameter(1).getParameter(0), pred,
135-
succ)
136-
)
137-
}
138-
}
42+
override string getSourceType() { result = "parsed user value from Formidable" }
13943
}
14044

14145
/**
142-
* A module for modeling [dicer](https://www.npmjs.com/package/dicer) package
46+
* A source of remote flow from the `Multiparty` library.
14347
*/
144-
module Dicer {
145-
/**
146-
* A source of remote flow from the `dicer` library.
147-
*/
148-
private class DicerRemoteFlow extends RemoteFlowSource {
149-
DicerRemoteFlow() {
150-
exists(API::Node dicer | dicer = API::moduleImport("dicer").getInstance() |
151-
exists(API::Node on | on = dicer.getMember("on") |
152-
on.getParameter(0).asSink().mayHaveStringValue("part") and
153-
this = readableStreamDataNode(on.getParameter(1).getParameter(0))
154-
or
155-
exists(API::Node onPart | onPart = on.getParameter(1).getParameter(0).getMember("on") |
156-
onPart.getParameter(0).asSink().mayHaveStringValue("header") and
157-
this = onPart.getParameter(1).getParameter(0).asSource()
158-
)
159-
)
48+
private class MultipartyRemoteFlow extends RemoteFlowSource {
49+
MultipartyRemoteFlow() {
50+
exists(API::Node form | form = API::moduleImport("multiparty").getMember("Form").getInstance() |
51+
exists(API::CallNode parse | parse = form.getMember("parse").getACall() |
52+
this = parse.getParameter(1).getAParameter().asSource()
16053
)
161-
}
162-
163-
override string getSourceType() { result = "parsed user value from Dicer" }
164-
}
165-
166-
/**
167-
* A dicer part data step according to a Readable Stream type
168-
*/
169-
private class AdditionalTaintStep extends TaintTracking::SharedTaintStep {
170-
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
171-
exists(API::Node onEvent |
172-
onEvent = API::moduleImport("dicer").getInstance().getMember("on")
173-
|
174-
onEvent.getParameter(0).asSink().mayHaveStringValue("part") and
175-
customStreamPipeAdditionalTaintStep(onEvent.getParameter(1).getParameter(0), pred, succ)
54+
or
55+
exists(API::CallNode on | on = form.getMember("on").getACall() |
56+
on.getArgument(0).mayHaveStringValue(["part", "file", "field"]) and
57+
this = on.getParameter(1).getAParameter().asSource()
17658
)
177-
}
59+
)
17860
}
61+
62+
override string getSourceType() { result = "parsed user value from Multiparty" }
17963
}

javascript/ql/src/experimental/Security/CWE-522-DecompressionBombs/DecompressionBombs.ql

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,15 @@
1212
*/
1313

1414
import javascript
15-
import semmle.javascript.frameworks.ReadableStream
1615
import DataFlow::PathGraph
1716
import DecompressionBombs
1817

1918
class BombConfiguration extends TaintTracking::Configuration {
2019
BombConfiguration() { this = "DecompressionBombs" }
2120

22-
override predicate isSource(DataFlow::Node source) {
23-
source instanceof RemoteFlowSource
24-
}
21+
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
2522

26-
override predicate isSink(DataFlow::Node sink) {
27-
sink instanceof DecompressionBomb::Sink
28-
}
23+
override predicate isSink(DataFlow::Node sink) { sink instanceof DecompressionBomb::Sink }
2924

3025
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
3126
exists(DecompressionBomb::AdditionalTaintStep addstep |

javascript/ql/src/experimental/Security/CWE-522-DecompressionBombs/DecompressionBombs.qll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import javascript
2-
import semmle.javascript.frameworks.ReadableStream
2+
import experimental.semmle.javascript.FormParsers
3+
import experimental.semmle.javascript.ReadableStream
34
import DataFlow::PathGraph
45

56
module DecompressionBomb {

0 commit comments

Comments
 (0)