@@ -39,6 +39,17 @@ class ConstantStateFlowConf extends DataFlow::Configuration {
39
39
override predicate isSink ( DataFlow:: Node sink ) { isSink ( sink , _) }
40
40
}
41
41
42
+ /**
43
+ * Holds if `pred` writes a URL to the `RedirectURL` field of the `succ` `Config` object.
44
+ *
45
+ * This propagates flow from the RedirectURL field to the whole Config object.
46
+ */
47
+ predicate isUrlTaintingConfigStep ( DataFlow:: Node pred , DataFlow:: Node succ ) {
48
+ exists ( Write w , Field f | f .hasQualifiedName ( "golang.org/x/oauth2" , "Config" , "RedirectURL" ) |
49
+ w .writesField ( succ .( DataFlow:: PostUpdateNode ) .getPreUpdateNode ( ) , f , pred )
50
+ )
51
+ }
52
+
42
53
/**
43
54
* A flow of a URL indicating the OAuth redirect doesn't point to a publicly
44
55
* accessible address, to the receiver of an `AuthCodeURL` call.
@@ -53,23 +64,12 @@ class PrivateUrlFlowsToAuthCodeUrlCall extends DataFlow::Configuration {
53
64
// The following are all common ways to indicate out-of-band OAuth2 flow, in which case
54
65
// the authenticating party does not redirect but presents a code for the user to copy
55
66
// instead.
56
- source .asExpr ( ) . ( StringLit ) . getValue ( ) in [ "urn:ietf:wg:oauth:2.0:oob" ,
57
- "urn:ietf:wg:oauth:2.0:oob:auto" , " oob", "code" ] or
67
+ source .getStringValue ( ) in [ "urn:ietf:wg:oauth:2.0:oob" , "urn:ietf:wg:oauth:2.0:oob:auto ",
68
+ "oob" , "code" ] or
58
69
// Alternatively some non-web tools will create a temporary local webserver to handle the
59
70
// OAuth2 redirect:
60
- source .asExpr ( ) .( StringLit ) .getValue ( ) .matches ( "%://localhost%" ) or
61
- source .asExpr ( ) .( StringLit ) .getValue ( ) .matches ( "%://127.0.0.1%" )
62
- }
63
-
64
- /**
65
- * Holds if `pred` writes a URL to the `RedirectURL` field of the `succ` `Config` object.
66
- *
67
- * This propagates flow from the RedirectURL field to the whole Config object.
68
- */
69
- predicate isUrlTaintingConfigStep ( DataFlow:: Node pred , DataFlow:: Node succ ) {
70
- exists ( Write w , Field f | f .hasQualifiedName ( "golang.org/x/oauth2" , "Config" , "RedirectURL" ) |
71
- w .writesField ( succ .( DataFlow:: PostUpdateNode ) .getPreUpdateNode ( ) , f , pred )
72
- )
71
+ source .getStringValue ( ) .matches ( "%://localhost%" ) or
72
+ source .getStringValue ( ) .matches ( "%://127.0.0.1%" )
73
73
}
74
74
75
75
override predicate isAdditionalFlowStep ( DataFlow:: Node pred , DataFlow:: Node succ ) {
@@ -80,11 +80,7 @@ class PrivateUrlFlowsToAuthCodeUrlCall extends DataFlow::Configuration {
80
80
TaintTracking:: referenceStep ( pred , succ )
81
81
or
82
82
// Propagate across Sprintf and similar calls
83
- exists ( DataFlow:: CallNode c |
84
- c = any ( Fmt:: Sprinter s ) .getACall ( ) and
85
- pred = c .getAnArgument ( ) and
86
- succ = c .getResult ( )
87
- )
83
+ TaintTracking:: functionModelStep ( any ( Fmt:: Sprinter s ) , pred , succ )
88
84
}
89
85
90
86
predicate isSink ( DataFlow:: Node sink , DataFlow:: CallNode call ) {
@@ -113,8 +109,6 @@ class FlowToPrint extends DataFlow::Configuration {
113
109
FlowToPrint ( ) { this = "FlowToPrint" }
114
110
115
111
predicate isSink ( DataFlow:: Node sink , DataFlow:: CallNode call ) {
116
- exists ( Fmt:: Printer printer | call = printer .getACall ( ) | sink = call .getArgument ( _) )
117
- or
118
112
exists ( LoggerCall logCall | call = logCall | sink = logCall .getAMessageComponent ( ) )
119
113
}
120
114
@@ -135,26 +129,32 @@ predicate resultFlowsToPrinter(DataFlow::CallNode authCodeURLCall) {
135
129
136
130
/** Get a data-flow node that reads the value of `os.Stdin`. */
137
131
DataFlow:: Node getAStdinNode ( ) {
138
- result = any ( ValueEntity v | v .hasQualifiedName ( "os" , "Stdin" ) ) .getARead ( )
132
+ exists ( ValueEntity v |
133
+ v .hasQualifiedName ( "os" , "Stdin" ) and result = globalValueNumber ( v .getARead ( ) ) .getANode ( )
134
+ )
139
135
}
140
136
141
137
/**
142
138
* Gets a call to a scanner function that reads from `os.Stdin`, or which creates a scanner
143
139
* instance wrapping `os.Stdin`.
144
140
*/
145
141
DataFlow:: CallNode getAScannerCall ( ) {
146
- result instanceof Fmt:: ScannerCall or
147
- result .( Fmt:: FScannerCall ) .getReader ( ) = getAStdinNode ( ) or
148
- result .( Bufio:: NewScannerCall ) .getReader ( ) = getAStdinNode ( )
142
+ result = any ( Fmt:: Scanner f ) .getACall ( )
143
+ or
144
+ exists ( Fmt:: FScanner f |
145
+ result = f .getACall ( ) and f .getReader ( ) .getNode ( result ) = getAStdinNode ( )
146
+ )
147
+ or
148
+ exists ( Bufio:: NewScanner f |
149
+ result = f .getACall ( ) and f .getReader ( ) .getNode ( result ) = getAStdinNode ( )
150
+ )
149
151
}
150
152
151
153
/**
152
154
* Holds if the provided `CallNode` is within the same root as a call
153
155
* to a scanner that reads from `os.Stdin`.
154
156
*/
155
- predicate containsCallToStdinScanner ( FuncDef funcDef ) {
156
- exists ( DataFlow:: CallNode call | call = getAScannerCall ( ) | call .getRoot ( ) = funcDef )
157
- }
157
+ predicate containsCallToStdinScanner ( FuncDef funcDef ) { getAScannerCall ( ) .getRoot ( ) = funcDef }
158
158
159
159
/**
160
160
* Holds if the `authCodeURLCall` seems to be done within a terminal
0 commit comments