@@ -49,20 +49,40 @@ module InsecureCookie {
4949 }
5050
5151 /**
52- * Holds if cookie attribute `attrib` (`secure` or `partitioned`) is set to `value` (`true` or `false`) at `node`.
53- * A value that cannot be determined is treated as `false`.
52+ * Holds if a models-as-data optional barrier for cookies is specified for `summaryNode`,
53+ * with arguments `attrib` (`secure` or `partitioned`) and `arg` (argument index). For example,
54+ * if a summary has input:
55+ * ```
56+ * [..., Argument[self].OptionalBarrier[cookie-secure-arg0], ...]
57+ * ```
58+ * then `attrib` is `secure` and `arg` is `0`.
5459 *
55- * This references models-as-data optional barrier nodes, for example `OptionalBarrier[cookie-secure-arg0]`.
60+ * The meaning here is that a call to the function summarized by `summaryNode` would set
61+ * the cookie attribute `attrib` to the value of argument `arg`. This may in practice be
62+ * interpretted as a barrier to flow (when the cookie is made secure) or as a source (when
63+ * the cookie is made insecure).
5664 */
57- predicate cookieSetNode ( DataFlow:: Node node , string attrib , boolean value ) {
58- exists (
59- FlowSummaryNode summaryNode , string barrierName , CallExprBase ce , int arg ,
60- DataFlow:: Node argNode
61- |
62- // decode a `cookie-`... optional barrier
65+ private predicate cookieOptionalBarrier ( FlowSummaryNode summaryNode , string attrib , int arg ) {
66+ exists ( string barrierName |
6367 DataFlowImpl:: optionalBarrier ( summaryNode , barrierName ) and
6468 attrib = barrierName .regexpCapture ( "cookie-(secure|partitioned)-arg([0-9]+)" , 1 ) and
65- arg = barrierName .regexpCapture ( "cookie-(secure|partitioned)-arg([0-9]+)" , 2 ) .toInt ( ) and
69+ arg = barrierName .regexpCapture ( "cookie-(secure|partitioned)-arg([0-9]+)" , 2 ) .toInt ( )
70+ )
71+ }
72+
73+ /**
74+ * Holds if cookie attribute `attrib` (`secure` or `partitioned`) is set to `value`
75+ * (`true` or `false`) at `node`. For example, the call:
76+ * ```
77+ * cookie.secure(true)
78+ * ```
79+ * sets the `"secure"` attribute to `true`. A value that cannot be determined is treated
80+ * as `false`.
81+ */
82+ predicate cookieSetNode ( DataFlow:: Node node , string attrib , boolean value ) {
83+ exists ( FlowSummaryNode summaryNode , CallExprBase ce , int arg , DataFlow:: Node argNode |
84+ // decode the models-as-data `OptionalBarrier`
85+ cookieOptionalBarrier ( summaryNode , attrib , arg ) and
6686 // find a call and arg referenced by this optional barrier
6787 ce .getStaticTarget ( ) = summaryNode .getSummarizedCallable ( ) and
6888 ce .getArg ( arg ) = argNode .asExpr ( ) .getExpr ( ) and
@@ -78,7 +98,8 @@ module InsecureCookie {
7898 then value = true // `true` flows to here
7999 else value = false // `false`, unknown, or multiple values
80100 ) and
81- // and find the node where this happens
101+ // and find the node where this happens (we can't just use the flow summary node, since its
102+ // shared across all calls to the modelled function, we need a node specific to this call)
82103 (
83104 node .asExpr ( ) .getExpr ( ) = ce .( MethodCallExpr ) .getReceiver ( ) // e.g. `a` in `a.set_secure(true)`
84105 or
0 commit comments