@@ -10,36 +10,86 @@ import PropertyInjectionShared
10
10
private import semmle.javascript.dataflow.InferredTypes
11
11
12
12
module UnvalidatedDynamicMethodCall {
13
- private import DataFlow:: FlowLabel
13
+ private newtype TFlowState =
14
+ TTaint ( ) or
15
+ TMaybeNonFunction ( ) or
16
+ TMaybeFromProto ( )
17
+
18
+ /** A flow state to associate with a tracked value. */
19
+ class FlowState extends TFlowState {
20
+ /** Gets a string representation fo this flow state */
21
+ string toString ( ) {
22
+ this = TTaint ( ) and result = "taint"
23
+ or
24
+ this = TMaybeNonFunction ( ) and result = "maybe-non-function"
25
+ or
26
+ this = TMaybeFromProto ( ) and result = "maybe-from-proto"
27
+ }
28
+
29
+ deprecated DataFlow:: FlowLabel toFlowLabel ( ) {
30
+ this = TTaint ( ) and result .isTaint ( )
31
+ or
32
+ this = TMaybeNonFunction ( ) and result instanceof MaybeNonFunction
33
+ or
34
+ this = TMaybeFromProto ( ) and result instanceof MaybeFromProto
35
+ }
36
+ }
37
+
38
+ /** Predicates for working with flow states. */
39
+ module FlowState {
40
+ deprecated FlowState fromFlowLabel ( DataFlow:: FlowLabel label ) { result .toFlowLabel ( ) = label }
41
+
42
+ /** A tainted value. */
43
+ FlowState taint ( ) { result = TTaint ( ) }
44
+
45
+ /**
46
+ * A non-function value, obtained by reading from a tainted property name.
47
+ */
48
+ FlowState maybeNonFunction ( ) { result = TMaybeNonFunction ( ) }
49
+
50
+ /**
51
+ * A value obtained from a prototype object while reading from a tainted property name.
52
+ */
53
+ FlowState maybeFromProto ( ) { result = TMaybeFromProto ( ) }
54
+ }
14
55
15
56
/**
16
57
* A data flow source for unvalidated dynamic method calls.
17
58
*/
18
59
abstract class Source extends DataFlow:: Node {
19
60
/**
20
- * Gets the flow label relevant for this source.
61
+ * Gets the flow state relevant for this source.
21
62
*/
22
- DataFlow:: FlowLabel getFlowLabel ( ) { result = taint ( ) }
63
+ FlowState getAFlowState ( ) { result = FlowState:: taint ( ) }
64
+
65
+ /** DEPRECATED. Use `getAFlowState()` instead. */
66
+ deprecated DataFlow:: FlowLabel getFlowLabel ( ) { result = this .getAFlowState ( ) .toFlowLabel ( ) }
23
67
}
24
68
25
69
/**
26
70
* A data flow sink for unvalidated dynamic method calls.
27
71
*/
28
72
abstract class Sink extends DataFlow:: Node {
29
73
/**
30
- * Gets the flow label relevant for this sink
74
+ * Gets the flow state relevant for this sink
31
75
*/
32
- abstract DataFlow:: FlowLabel getFlowLabel ( ) ;
76
+ FlowState getAFlowState ( ) { result = FlowState:: taint ( ) }
77
+
78
+ /** DEPRECATED. Use `getAFlowState()` instead. */
79
+ deprecated DataFlow:: FlowLabel getFlowLabel ( ) { result = this .getAFlowState ( ) .toFlowLabel ( ) }
33
80
}
34
81
35
82
/**
36
83
* A sanitizer for unvalidated dynamic method calls.
37
84
*/
38
85
abstract class Sanitizer extends DataFlow:: Node {
39
86
/**
40
- * Gets the flow label blocked by this sanitizer.
87
+ * Gets a flow state blocked by this sanitizer.
41
88
*/
42
- DataFlow:: FlowLabel getFlowLabel ( ) { result .isTaint ( ) }
89
+ FlowState getAFlowState ( ) { result = FlowState:: taint ( ) }
90
+
91
+ /** DEPRECATED. Use `getAFlowState()` instead. */
92
+ deprecated DataFlow:: FlowLabel getFlowLabel ( ) { result = this .getAFlowState ( ) .toFlowLabel ( ) }
43
93
44
94
/**
45
95
* DEPRECATED. Use sanitizer nodes instead.
@@ -64,16 +114,16 @@ module UnvalidatedDynamicMethodCall {
64
114
predicate blocksExpr ( boolean outcome , Expr e ) { none ( ) }
65
115
66
116
/**
67
- * Holds if this node acts as a barrier for `label `, blocking further flow from `e` if `this` evaluates to `outcome`.
117
+ * Holds if this node acts as a barrier for `state `, blocking further flow from `e` if `this` evaluates to `outcome`.
68
118
*/
69
- predicate blocksExpr ( boolean outcome , Expr e , DataFlow :: FlowLabel label ) { none ( ) }
119
+ predicate blocksExpr ( boolean outcome , Expr e , FlowState state ) { none ( ) }
70
120
71
121
/** DEPRECATED. Use `blocksExpr` instead. */
72
122
deprecated predicate sanitizes ( boolean outcome , Expr e ) { this .blocksExpr ( outcome , e ) }
73
123
74
124
/** DEPRECATED. Use `blocksExpr` instead. */
75
125
deprecated predicate sanitizes ( boolean outcome , Expr e , DataFlow:: FlowLabel label ) {
76
- this .blocksExpr ( outcome , e , label )
126
+ this .blocksExpr ( outcome , e , FlowState :: fromFlowLabel ( label ) )
77
127
}
78
128
}
79
129
@@ -93,15 +143,15 @@ module UnvalidatedDynamicMethodCall {
93
143
* A flow label describing values read from a user-controlled property that
94
144
* may not be functions.
95
145
*/
96
- abstract class MaybeNonFunction extends DataFlow:: FlowLabel {
146
+ abstract deprecated class MaybeNonFunction extends DataFlow:: FlowLabel {
97
147
MaybeNonFunction ( ) { this = "MaybeNonFunction" }
98
148
}
99
149
100
150
/**
101
151
* A flow label describing values read from a user-controlled property that
102
152
* may originate from a prototype object.
103
153
*/
104
- abstract class MaybeFromProto extends DataFlow:: FlowLabel {
154
+ abstract deprecated class MaybeFromProto extends DataFlow:: FlowLabel {
105
155
MaybeFromProto ( ) { this = "MaybeFromProto" }
106
156
}
107
157
@@ -134,14 +184,14 @@ module UnvalidatedDynamicMethodCall {
134
184
)
135
185
}
136
186
137
- override DataFlow :: FlowLabel getFlowLabel ( ) {
138
- result instanceof MaybeNonFunction and
187
+ override FlowState getAFlowState ( ) {
188
+ result = FlowState :: maybeNonFunction ( ) and
139
189
// don't flag if the type inference can prove that it is a function;
140
190
// this complements the `FunctionCheck` sanitizer below: the type inference can
141
191
// detect more checks locally, but doesn't provide inter-procedural reasoning
142
192
this .analyze ( ) .getAType ( ) != TTFunction ( )
143
193
or
144
- result instanceof MaybeFromProto
194
+ result = FlowState :: maybeFromProto ( )
145
195
}
146
196
}
147
197
@@ -155,10 +205,10 @@ module UnvalidatedDynamicMethodCall {
155
205
156
206
FunctionCheck ( ) { TaintTracking:: isTypeofGuard ( astNode , operand , "function" ) }
157
207
158
- override predicate blocksExpr ( boolean outcome , Expr e , DataFlow :: FlowLabel label ) {
208
+ override predicate blocksExpr ( boolean outcome , Expr e , FlowState state ) {
159
209
outcome = astNode .getPolarity ( ) and
160
210
e = operand and
161
- label instanceof MaybeNonFunction
211
+ state = FlowState :: maybeNonFunction ( )
162
212
}
163
213
}
164
214
0 commit comments