1
1
import python
2
2
3
- /** A Class that is a Django Response (subclass of `django.http.HttpResponse`). */
4
- class DjangoResponse extends ClassValue {
3
+ /** A class that is a Django Redirect Response (subclass of `django.http.HttpResponseRedirectBase`). */
4
+ class DjangoRedirectResponseClass extends ClassValue {
5
+ DjangoRedirectResponseClass ( ) {
6
+ exists ( ClassValue redirect_base |
7
+ // version 1.x
8
+ redirect_base = Value:: named ( "django.http.response.HttpResponseRedirectBase" )
9
+ or
10
+ // version 2.x and 3.x
11
+ redirect_base = Value:: named ( "django.http.HttpResponseRedirectBase" )
12
+ |
13
+ this .getASuperType ( ) = redirect_base
14
+ )
15
+ }
16
+ }
17
+
18
+ /**
19
+ * A class that is a Django Response, which can contain content.
20
+ * A subclass of `django.http.HttpResponse` that is not a `DjangoRedirectResponseClass`.
21
+ */
22
+ class DjangoContentResponseClass extends ClassValue {
5
23
ClassValue base ;
6
24
7
- DjangoResponse ( ) {
25
+ DjangoContentResponseClass ( ) {
8
26
(
9
27
// version 1.x
10
28
base = Value:: named ( "django.http.response.HttpResponse" )
@@ -15,49 +33,39 @@ class DjangoResponse extends ClassValue {
15
33
) and
16
34
this .getASuperType ( ) = base
17
35
}
18
- }
19
36
20
- /** A Class that is a Django Redirect Response (subclass of `django.http.HttpResponseRedirectBase`). */
21
- class DjangoRedirectResponse extends DjangoResponse {
22
- DjangoRedirectResponse ( ) {
23
- exists ( ClassValue redirect_base |
24
- // version 1.x
25
- redirect_base = Value:: named ( "django.http.response.HttpResponseRedirectBase" )
26
- or
27
- // version 2.x and 3.x
28
- redirect_base = Value:: named ( "django.http.HttpResponseRedirectBase" )
29
- |
30
- this .getASuperType ( ) = redirect_base
31
- )
32
- }
37
+ // The reason these two method are defined in this class (and not in the Sink
38
+ // definition that uses this class), is that if we were to add support for
39
+ // `django.http.response.HttpResponseNotAllowed` it would make much more sense to add
40
+ // the custom logic in this class (or subclass), than to handle all of it in the sink
41
+ // definition.
42
+
43
+ /** Gets the `content` argument of a `call` to the constructor */
44
+ ControlFlowNode getContentArg ( CallNode call ) { none ( ) }
45
+
46
+ /** Gets the `content_type` argument of a `call` to the constructor */
47
+ ControlFlowNode getContentTypeArg ( CallNode call ) { none ( ) }
33
48
}
34
49
35
50
/** A Class that is a Django Response, and is vulnerable to XSS. */
36
- class DjangoXSSVulnerableResponse extends DjangoResponse {
37
- DjangoXSSVulnerableResponse ( ) {
51
+ class DjangoXSSVulnerableResponseClass extends DjangoContentResponseClass {
52
+ DjangoXSSVulnerableResponseClass ( ) {
38
53
// We want to avoid FPs on subclasses that are not exposed to XSS, for example `JsonResponse`.
39
54
// The easiest way is to disregard any subclass that has a special `__init__` method.
40
55
// It's not guaranteed to remove all FPs, or not to generate FNs, but compared to our
41
56
// previous implementation that would treat 0-th argument to _any_ subclass as a sink,
42
57
// this gets us much closer to reality.
43
58
this .lookup ( "__init__" ) = base .lookup ( "__init__" ) and
44
- not this instanceof DjangoRedirectResponse
59
+ not this instanceof DjangoRedirectResponseClass
45
60
}
46
61
47
- // The reason these two method are defined in this class (and no in the Sink
48
- // definition that uses this class), is that if we were to add support for `HttpResponseNotAllowed`
49
- // it would make much more sense to add the custom logic in this class (or subclass), than to handle all of it
50
- // in the sink definition.
51
-
52
- /** Gets the `content` argument of a `call` to the constructor */
53
- ControlFlowNode getContentArg ( CallNode call ) {
62
+ override ControlFlowNode getContentArg ( CallNode call ) {
54
63
result = call .getArg ( 0 )
55
64
or
56
65
result = call .getArgByName ( "content" )
57
66
}
58
67
59
- /** Gets the `content_type` argument of a `call` to the constructor */
60
- ControlFlowNode getContentTypeArg ( CallNode call ) {
68
+ override ControlFlowNode getContentTypeArg ( CallNode call ) {
61
69
result = call .getArg ( 1 )
62
70
or
63
71
result = call .getArgByName ( "content_type" )
0 commit comments