|
3 | 3 | */ |
4 | 4 |
|
5 | 5 | import javascript |
6 | | -import semmle.javascript.frameworks.ReadableStream |
7 | 6 |
|
8 | 7 | /** |
9 | | - * A module for modeling [busboy](https://www.npmjs.com/package/busboy) package |
| 8 | + * A source of remote flow from the `Busboy` library. |
10 | 9 | */ |
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() |
38 | 19 | } |
39 | 20 |
|
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" } |
54 | 22 | } |
55 | 23 |
|
56 | 24 | /** |
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. |
58 | 26 | */ |
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 | + ) |
90 | 40 | } |
91 | | -} |
92 | 41 |
|
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" } |
139 | 43 | } |
140 | 44 |
|
141 | 45 | /** |
142 | | - * A module for modeling [dicer](https://www.npmjs.com/package/dicer) package |
| 46 | + * A source of remote flow from the `Multiparty` library. |
143 | 47 | */ |
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() |
160 | 53 | ) |
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() |
176 | 58 | ) |
177 | | - } |
| 59 | + ) |
178 | 60 | } |
| 61 | + |
| 62 | + override string getSourceType() { result = "parsed user value from Multiparty" } |
179 | 63 | } |
0 commit comments