Skip to content

Commit 57f8487

Browse files
committed
Rust: Split off cookieOptionalBarrier predicate (as suggested) and expand / clarify the QLDoc.
1 parent 21fe142 commit 57f8487

File tree

1 file changed

+32
-11
lines changed

1 file changed

+32
-11
lines changed

rust/ql/lib/codeql/rust/security/InsecureCookieExtensions.qll

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)