@@ -45,31 +45,31 @@ module Cookie {
4545 * Holds if the cookie is authentication sensitive and lacks HttpOnly.
4646 */
4747 abstract predicate isAuthNotHttpOnly ( ) ;
48+ }
4849
49- /**
50- * Holds if the expression is a variable with a sensitive name.
51- */
52- predicate isAuthVariable ( DataFlow:: Node expr ) {
53- exists ( string val |
54- (
55- val = expr .getStringValue ( ) or
56- val = expr .asExpr ( ) .( VarAccess ) .getName ( ) or
57- val = expr .( DataFlow:: PropRead ) .getPropertyName ( )
58- ) and
59- regexpMatchAuth ( val )
60- )
61- or
62- isAuthVariable ( expr .getAPredecessor ( ) )
63- }
50+ /**
51+ * Holds if the expression is a variable with a sensitive name.
52+ */
53+ private predicate isAuthVariable ( DataFlow:: Node expr ) {
54+ exists ( string val |
55+ (
56+ val = expr .getStringValue ( ) or
57+ val = expr .asExpr ( ) .( VarAccess ) .getName ( ) or
58+ val = expr .( DataFlow:: PropRead ) .getPropertyName ( )
59+ ) and
60+ regexpMatchAuth ( val )
61+ )
62+ or
63+ isAuthVariable ( expr .getAPredecessor ( ) )
64+ }
6465
65- /**
66- * Holds if the string contains sensitive auth keyword, but not antiforgery token.
67- */
68- bindingset [ val]
69- predicate regexpMatchAuth ( string val ) {
70- val .regexpMatch ( "(?i).*(session|login|token|user|auth|credential).*" ) and
71- not val .regexpMatch ( "(?i).*(xsrf|csrf|forgery).*" )
72- }
66+ /**
67+ * Holds if the string contains sensitive auth keyword, but not antiforgery token.
68+ */
69+ bindingset [ val]
70+ private predicate regexpMatchAuth ( string val ) {
71+ val .regexpMatch ( "(?i).*(session|login|token|user|auth|credential).*" ) and
72+ not val .regexpMatch ( "(?i).*(xsrf|csrf|forgery).*" )
7373 }
7474
7575 /**
@@ -168,6 +168,26 @@ module Cookie {
168168 }
169169 }
170170
171+ private class AttributeToSetCookieHeaderTrackingConfig extends TaintTracking:: Configuration {
172+ AttributeToSetCookieHeaderTrackingConfig ( ) { this = "AttributeToSetCookieHeaderTrackingConfig" }
173+
174+ override predicate isSource ( DataFlow:: Node source ) {
175+ exists ( string s | source .mayHaveStringValue ( s ) )
176+ }
177+
178+ override predicate isSink ( DataFlow:: Node sink ) { sink .asExpr ( ) instanceof TemplateLiteral }
179+ }
180+
181+ private class SensitiveNameToSetCookieHeaderTrackingConfig extends TaintTracking:: Configuration {
182+ SensitiveNameToSetCookieHeaderTrackingConfig ( ) {
183+ this = "SensitiveNameToSetCookieHeaderTrackingConfig"
184+ }
185+
186+ override predicate isSource ( DataFlow:: Node source ) { isAuthVariable ( source ) }
187+
188+ override predicate isSink ( DataFlow:: Node sink ) { sink .asExpr ( ) instanceof TemplateLiteral }
189+ }
190+
171191 /**
172192 * A cookie set using `Set-Cookie` header of an `HTTP` response.
173193 * (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie).
@@ -197,7 +217,7 @@ module Cookie {
197217 * A cookie is httpOnly if the `httpOnly` flag is specified in the cookie definition.
198218 * The default is `false`.
199219 */
200- override predicate isHttpOnly ( ) { allHaveCookieAttribute ( "httponly" ) }
220+ override predicate isHttpOnly ( ) { allHaveCookieAttribute ( httpOnlyFlag ( ) ) }
201221
202222 /**
203223 * The predicate holds only if all elements have the specified attribute.
@@ -209,6 +229,14 @@ module Cookie {
209229 n .mayHaveStringValue ( s ) and
210230 hasCookieAttribute ( s , attribute )
211231 )
232+ or
233+ exists ( AttributeToSetCookieHeaderTrackingConfig cfg , DataFlow:: Node source |
234+ cfg .hasFlow ( source , n ) and
235+ exists ( string attr |
236+ source .mayHaveStringValue ( attr ) and
237+ attr .regexpMatch ( "(?i).*\\b" + attribute + "\\b.*" )
238+ )
239+ )
212240 )
213241 }
214242
@@ -221,10 +249,19 @@ module Cookie {
221249 exists ( string s |
222250 n .mayHaveStringValue ( s ) and
223251 (
224- not hasCookieAttribute ( s , "httponly" ) and
252+ not hasCookieAttribute ( s , httpOnlyFlag ( ) ) and
225253 regexpMatchAuth ( getCookieName ( s ) )
226254 )
227255 )
256+ or
257+ not exists ( AttributeToSetCookieHeaderTrackingConfig cfg , DataFlow:: Node source |
258+ cfg .hasFlow ( source , n ) and
259+ exists ( string attr |
260+ source .mayHaveStringValue ( attr ) and
261+ attr .regexpMatch ( "(?i).*\\b" + httpOnlyFlag ( ) + "\\b.*" )
262+ )
263+ ) and
264+ exists ( SensitiveNameToSetCookieHeaderTrackingConfig cfg | cfg .hasFlow ( _, n ) )
228265 )
229266 }
230267
0 commit comments