|
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