Skip to content

Commit cf8db4e

Browse files
Update instances of experimental concept to the main one, and anotate missing experimental test results.
1 parent daa31b5 commit cf8db4e

File tree

8 files changed

+14
-130
lines changed

8 files changed

+14
-130
lines changed

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

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -216,47 +216,6 @@ class SqlEscape extends DataFlow::Node instanceof SqlEscape::Range {
216216
DataFlow::Node getAnInput() { result = super.getAnInput() }
217217
}
218218

219-
/** Provides classes for modeling HTTP Header APIs. */
220-
module HeaderDeclaration {
221-
/**
222-
* A data-flow node that collects functions setting HTTP Headers.
223-
*
224-
* Extend this class to model new APIs. If you want to refine existing API models,
225-
* extend `HeaderDeclaration` instead.
226-
*/
227-
abstract class Range extends DataFlow::Node {
228-
/**
229-
* Gets the argument containing the header name.
230-
*/
231-
abstract DataFlow::Node getNameArg();
232-
233-
/**
234-
* Gets the argument containing the header value.
235-
*/
236-
abstract DataFlow::Node getValueArg();
237-
}
238-
}
239-
240-
/**
241-
* A data-flow node that collects functions setting HTTP Headers.
242-
*
243-
* Extend this class to refine existing API models. If you want to model new APIs,
244-
* extend `HeaderDeclaration::Range` instead.
245-
*
246-
* Exists as `Http::Server::ResponseHeaderWrite` in the main concepts library.
247-
*/
248-
class HeaderDeclaration extends DataFlow::Node instanceof HeaderDeclaration::Range {
249-
/**
250-
* Gets the argument containing the header name.
251-
*/
252-
DataFlow::Node getNameArg() { result = super.getNameArg() }
253-
254-
/**
255-
* Gets the argument containing the header value.
256-
*/
257-
DataFlow::Node getValueArg() { result = super.getValueArg() }
258-
}
259-
260219
/** Provides classes for modeling Csv writer APIs. */
261220
module CsvWriter {
262221
/**

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

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import python
66
import semmle.python.dataflow.new.DataFlow
77
import semmle.python.dataflow.new.TaintTracking
88
import experimental.semmle.python.Concepts
9+
import semmle.python.Concepts
910

1011
/**
1112
* Gets a header setting a cookie.
@@ -26,13 +27,13 @@ import experimental.semmle.python.Concepts
2627
* * `isSameSite()` predicate would fail.
2728
* * `getName()` and `getValue()` results would be `"name=value; Secure;"`.
2829
*/
29-
class CookieHeader extends Cookie::Range instanceof HeaderDeclaration {
30+
class CookieHeader extends Cookie::Range instanceof Http::Server::ResponseHeaderWrite {
3031
CookieHeader() {
3132
exists(StringLiteral str |
3233
str.getText() = "Set-Cookie" and
3334
DataFlow::exprNode(str)
3435
.(DataFlow::LocalSourceNode)
35-
.flowsTo(this.(HeaderDeclaration).getNameArg())
36+
.flowsTo(this.(Http::Server::ResponseHeaderWrite).getNameArg())
3637
)
3738
}
3839

@@ -41,7 +42,7 @@ class CookieHeader extends Cookie::Range instanceof HeaderDeclaration {
4142
str.getText().regexpMatch(".*; *Secure;.*") and
4243
DataFlow::exprNode(str)
4344
.(DataFlow::LocalSourceNode)
44-
.flowsTo(this.(HeaderDeclaration).getValueArg())
45+
.flowsTo(this.(Http::Server::ResponseHeaderWrite).getValueArg())
4546
)
4647
}
4748

@@ -50,7 +51,7 @@ class CookieHeader extends Cookie::Range instanceof HeaderDeclaration {
5051
str.getText().regexpMatch(".*; *HttpOnly;.*") and
5152
DataFlow::exprNode(str)
5253
.(DataFlow::LocalSourceNode)
53-
.flowsTo(this.(HeaderDeclaration).getValueArg())
54+
.flowsTo(this.(Http::Server::ResponseHeaderWrite).getValueArg())
5455
)
5556
}
5657

@@ -59,13 +60,17 @@ class CookieHeader extends Cookie::Range instanceof HeaderDeclaration {
5960
str.getText().regexpMatch(".*; *SameSite=(Strict|Lax);.*") and
6061
DataFlow::exprNode(str)
6162
.(DataFlow::LocalSourceNode)
62-
.flowsTo(this.(HeaderDeclaration).getValueArg())
63+
.flowsTo(this.(Http::Server::ResponseHeaderWrite).getValueArg())
6364
)
6465
}
6566

66-
override DataFlow::Node getNameArg() { result = this.(HeaderDeclaration).getValueArg() }
67+
override DataFlow::Node getNameArg() {
68+
result = this.(Http::Server::ResponseHeaderWrite).getValueArg()
69+
}
6770

68-
override DataFlow::Node getValueArg() { result = this.(HeaderDeclaration).getValueArg() }
71+
override DataFlow::Node getValueArg() {
72+
result = this.(Http::Server::ResponseHeaderWrite).getValueArg()
73+
}
6974

7075
override DataFlow::Node getHeaderArg() { none() }
7176
}

python/ql/test/experimental/query-tests/Security/CWE-113/HeaderInjection.expected

Lines changed: 0 additions & 47 deletions
This file was deleted.

python/ql/test/experimental/query-tests/Security/CWE-113/HeaderInjection.qlref

Lines changed: 0 additions & 1 deletion
This file was deleted.

python/ql/test/experimental/query-tests/Security/CWE-113/django_bad.py

Lines changed: 0 additions & 15 deletions
This file was deleted.

python/ql/test/experimental/query-tests/Security/CWE-614/CookieInjection.expected

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
edges
2-
| django_bad.py:27:33:27:67 | ControlFlowNode for Attribute() | django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | provenance | |
3-
| django_bad.py:27:71:27:106 | ControlFlowNode for Attribute() | django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | provenance | |
42
| flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:1:26:1:32 | ControlFlowNode for request | provenance | |
53
| flask_bad.py:1:26:1:32 | ControlFlowNode for request | flask_bad.py:24:21:24:27 | ControlFlowNode for request | provenance | |
64
| flask_bad.py:1:26:1:32 | ControlFlowNode for request | flask_bad.py:24:49:24:55 | ControlFlowNode for request | provenance | |
@@ -14,9 +12,6 @@ edges
1412
nodes
1513
| django_bad.py:19:21:19:55 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
1614
| django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
17-
| django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | semmle.label | ControlFlowNode for Fstring |
18-
| django_bad.py:27:33:27:67 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
19-
| django_bad.py:27:71:27:106 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
2015
| flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember |
2116
| flask_bad.py:1:26:1:32 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
2217
| flask_bad.py:24:21:24:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
@@ -34,12 +29,6 @@ subpaths
3429
| django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | Cookie is constructed from a $@,and its httponly flag is not properly set. | django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | user-supplied input |
3530
| django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | Cookie is constructed from a $@,and its samesite flag is not properly set. | django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | user-supplied input |
3631
| django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | Cookie is constructed from a $@,and its secure flag is not properly set. | django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | user-supplied input |
37-
| django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | django_bad.py:27:33:27:67 | ControlFlowNode for Attribute() | django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its httponly flag is not properly set. | django_bad.py:27:33:27:67 | ControlFlowNode for Attribute() | user-supplied input |
38-
| django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | django_bad.py:27:33:27:67 | ControlFlowNode for Attribute() | django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its samesite flag is not properly set. | django_bad.py:27:33:27:67 | ControlFlowNode for Attribute() | user-supplied input |
39-
| django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | django_bad.py:27:33:27:67 | ControlFlowNode for Attribute() | django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its secure flag is not properly set. | django_bad.py:27:33:27:67 | ControlFlowNode for Attribute() | user-supplied input |
40-
| django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | django_bad.py:27:71:27:106 | ControlFlowNode for Attribute() | django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its httponly flag is not properly set. | django_bad.py:27:71:27:106 | ControlFlowNode for Attribute() | user-supplied input |
41-
| django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | django_bad.py:27:71:27:106 | ControlFlowNode for Attribute() | django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its samesite flag is not properly set. | django_bad.py:27:71:27:106 | ControlFlowNode for Attribute() | user-supplied input |
42-
| django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | django_bad.py:27:71:27:106 | ControlFlowNode for Attribute() | django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its secure flag is not properly set. | django_bad.py:27:71:27:106 | ControlFlowNode for Attribute() | user-supplied input |
4332
| flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its httponly flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input |
4433
| flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its samesite flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input |
4534
| flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its secure flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input |

python/ql/test/experimental/query-tests/Security/CWE-614/InsecureCookie.expected

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,9 @@
11
| django_bad.py:6:5:7:52 | ControlFlowNode for Attribute() | Cookie is added without the 'httponly' flag properly set. |
22
| django_bad.py:6:5:7:52 | ControlFlowNode for Attribute() | Cookie is added without the 'samesite' flag properly set. |
33
| django_bad.py:6:5:7:52 | ControlFlowNode for Attribute() | Cookie is added without the 'secure' flag properly set. |
4-
| django_bad.py:13:5:13:26 | ControlFlowNode for Subscript | Cookie is added without the 'httponly' flag properly set. |
5-
| django_bad.py:13:5:13:26 | ControlFlowNode for Subscript | Cookie is added without the 'samesite' flag properly set. |
6-
| django_bad.py:13:5:13:26 | ControlFlowNode for Subscript | Cookie is added without the 'secure' flag properly set. |
74
| django_bad.py:19:5:21:66 | ControlFlowNode for Attribute() | Cookie is added without the 'httponly' flag properly set. |
85
| django_bad.py:19:5:21:66 | ControlFlowNode for Attribute() | Cookie is added without the 'samesite' flag properly set. |
96
| django_bad.py:19:5:21:66 | ControlFlowNode for Attribute() | Cookie is added without the 'secure' flag properly set. |
10-
| django_bad.py:27:5:27:26 | ControlFlowNode for Subscript | Cookie is added without the 'httponly' flag properly set. |
11-
| django_bad.py:27:5:27:26 | ControlFlowNode for Subscript | Cookie is added without the 'samesite' flag properly set. |
12-
| django_bad.py:27:5:27:26 | ControlFlowNode for Subscript | Cookie is added without the 'secure' flag properly set. |
137
| django_good.py:19:5:19:44 | ControlFlowNode for Attribute() | Cookie is added without the 'httponly' flag properly set. |
148
| django_good.py:19:5:19:44 | ControlFlowNode for Attribute() | Cookie is added without the 'samesite' flag properly set. |
159
| django_good.py:19:5:19:44 | ControlFlowNode for Attribute() | Cookie is added without the 'secure' flag properly set. |

python/ql/test/experimental/query-tests/Security/CWE-614/django_bad.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ def django_response(request):
77
httponly=False, samesite='None')
88
return resp
99

10-
10+
# This test no longer produces an output due to django header setting methods not being modeled in the main query pack
1111
def django_response():
1212
response = django.http.HttpResponse()
1313
response['Set-Cookie'] = "name=value; SameSite=None;"
@@ -21,7 +21,7 @@ def django_response(request):
2121
secure=False, httponly=False, samesite='None')
2222
return resp
2323

24-
24+
# This test no longer produces an output due to django header setting methods not being modeled in the main query pack
2525
def django_response():
2626
response = django.http.HttpResponse()
2727
response['Set-Cookie'] = f"{django.http.request.GET.get('name')}={django.http.request.GET.get('value')}; SameSite=None;"

0 commit comments

Comments
 (0)