@@ -39,6 +39,17 @@ class ConstantStateFlowConf extends DataFlow::Configuration {
3939 override predicate isSink ( DataFlow:: Node sink ) { isSink ( sink , _) }
4040}
4141
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+
4253/**
4354 * A flow of a URL indicating the OAuth redirect doesn't point to a publicly
4455 * accessible address, to the receiver of an `AuthCodeURL` call.
@@ -53,23 +64,12 @@ class PrivateUrlFlowsToAuthCodeUrlCall extends DataFlow::Configuration {
5364 // The following are all common ways to indicate out-of-band OAuth2 flow, in which case
5465 // the authenticating party does not redirect but presents a code for the user to copy
5566 // 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
5869 // Alternatively some non-web tools will create a temporary local webserver to handle the
5970 // 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%" )
7373 }
7474
7575 override predicate isAdditionalFlowStep ( DataFlow:: Node pred , DataFlow:: Node succ ) {
@@ -80,11 +80,7 @@ class PrivateUrlFlowsToAuthCodeUrlCall extends DataFlow::Configuration {
8080 TaintTracking:: referenceStep ( pred , succ )
8181 or
8282 // 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 )
8884 }
8985
9086 predicate isSink ( DataFlow:: Node sink , DataFlow:: CallNode call ) {
@@ -113,8 +109,6 @@ class FlowToPrint extends DataFlow::Configuration {
113109 FlowToPrint ( ) { this = "FlowToPrint" }
114110
115111 predicate isSink ( DataFlow:: Node sink , DataFlow:: CallNode call ) {
116- exists ( Fmt:: Printer printer | call = printer .getACall ( ) | sink = call .getArgument ( _) )
117- or
118112 exists ( LoggerCall logCall | call = logCall | sink = logCall .getAMessageComponent ( ) )
119113 }
120114
@@ -135,26 +129,32 @@ predicate resultFlowsToPrinter(DataFlow::CallNode authCodeURLCall) {
135129
136130/** Get a data-flow node that reads the value of `os.Stdin`. */
137131DataFlow:: 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+ )
139135}
140136
141137/**
142138 * Gets a call to a scanner function that reads from `os.Stdin`, or which creates a scanner
143139 * instance wrapping `os.Stdin`.
144140 */
145141DataFlow:: 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+ )
149151}
150152
151153/**
152154 * Holds if the provided `CallNode` is within the same root as a call
153155 * to a scanner that reads from `os.Stdin`.
154156 */
155- predicate containsCallToStdinScanner ( FuncDef funcDef ) {
156- exists ( DataFlow:: CallNode call | call = getAScannerCall ( ) | call .getRoot ( ) = funcDef )
157- }
157+ predicate containsCallToStdinScanner ( FuncDef funcDef ) { getAScannerCall ( ) .getRoot ( ) = funcDef }
158158
159159/**
160160 * Holds if the `authCodeURLCall` seems to be done within a terminal
0 commit comments