Skip to content

Commit 6504429

Browse files
committed
Add CookieWrite concept
1 parent 66fdd53 commit 6504429

2 files changed

Lines changed: 69 additions & 0 deletions

File tree

python/ql/src/experimental/semmle/python/Concepts.qll

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,3 +252,61 @@ class HeaderDeclaration extends DataFlow::Node {
252252
*/
253253
DataFlow::Node getValueArg() { result = range.getValueArg() }
254254
}
255+
256+
module ExperimentalHTTP {
257+
/**
258+
* A data-flow node that sets a cookie in an HTTP response.
259+
*
260+
* Extend this class to refine existing API models. If you want to model new APIs,
261+
* extend `HTTP::CookieWrite::Range` instead.
262+
*/
263+
class CookieWrite extends DataFlow::Node {
264+
CookieWrite::Range range;
265+
266+
CookieWrite() { this = range }
267+
268+
/**
269+
* Gets the argument, if any, specifying the raw cookie header.
270+
*/
271+
DataFlow::Node getHeaderArg() { result = range.getHeaderArg() }
272+
273+
/**
274+
* Gets the argument, if any, specifying the cookie name.
275+
*/
276+
DataFlow::Node getNameArg() { result = range.getNameArg() }
277+
278+
/**
279+
* Gets the argument, if any, specifying the cookie value.
280+
*/
281+
DataFlow::Node getValueArg() { result = range.getValueArg() }
282+
}
283+
284+
/** Provides a class for modeling new cookie writes on HTTP responses. */
285+
module CookieWrite {
286+
/**
287+
* A data-flow node that sets a cookie in an HTTP response.
288+
*
289+
* Note: we don't require that this redirect must be sent to a client (a kind of
290+
* "if a tree falls in a forest and nobody hears it" situation).
291+
*
292+
* Extend this class to model new APIs. If you want to refine existing API models,
293+
* extend `HttpResponse` instead.
294+
*/
295+
abstract class Range extends DataFlow::Node {
296+
/**
297+
* Gets the argument, if any, specifying the raw cookie header.
298+
*/
299+
abstract DataFlow::Node getHeaderArg();
300+
301+
/**
302+
* Gets the argument, if any, specifying the cookie name.
303+
*/
304+
abstract DataFlow::Node getNameArg();
305+
306+
/**
307+
* Gets the argument, if any, specifying the cookie value.
308+
*/
309+
abstract DataFlow::Node getValueArg();
310+
}
311+
}
312+
}

python/ql/src/experimental/semmle/python/frameworks/Django.qll

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,17 @@ private module PrivateDjango {
7575

7676
override DataFlow::Node getValueArg() { result = headerInput }
7777
}
78+
79+
class DjangoSetCookieCall extends DataFlow::CallCfgNode,
80+
ExperimentalHTTP::CookieWrite::Range {
81+
DjangoSetCookieCall() { this = baseClassRef().getMember("set_cookie").getACall() }
82+
83+
override DataFlow::Node getHeaderArg() { none() }
84+
85+
override DataFlow::Node getNameArg() { result = this.getArg(0) }
86+
87+
override DataFlow::Node getValueArg() { result = this.getArg(1) }
88+
}
7889
}
7990
}
8091
}

0 commit comments

Comments
 (0)