Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 52be896

Browse files
Rasmus Lerchedahl PetersenRasmus Lerchedahl Petersen
authored andcommitted
Python: django.http.response.JsonResponse
It s possible this class is not relevant to XSS
1 parent 0f9b859 commit 52be896

2 files changed

Lines changed: 68 additions & 3 deletions

File tree

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

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,7 @@ private module Django {
499499
* WARNING: Only holds for a few predefined attributes.
500500
*/
501501
private DataFlow::Node http_attr(DataFlow::TypeTracker t, string attr_name) {
502-
attr_name in ["request", "HttpRequest", "response", "HttpResponse"] and
502+
attr_name in ["request", "HttpRequest", "response", "HttpResponse", "JsonResponse"] and
503503
(
504504
t.start() and
505505
result = DataFlow::importNode("django.http" + "." + attr_name)
@@ -641,7 +641,7 @@ private module Django {
641641
* WARNING: Only holds for a few predefined attributes.
642642
*/
643643
private DataFlow::Node response_attr(DataFlow::TypeTracker t, string attr_name) {
644-
attr_name in ["HttpResponse"] and
644+
attr_name in ["HttpResponse", "JsonResponse"] and
645645
(
646646
t.start() and
647647
result = DataFlow::importNode("django.http.response" + "." + attr_name)
@@ -739,6 +739,71 @@ private module Django {
739739
/** Gets a reference to an instance of `django.http.response.HttpResponse`. */
740740
DataFlow::Node instance() { result = instance(DataFlow::TypeTracker::end()) }
741741
}
742+
743+
// ---------------------------------------------------------------------------
744+
// HttpResponse subclasses
745+
// ---------------------------------------------------------------------------
746+
/**
747+
* Provides models for the `django.http.response.JsonResponse` class
748+
*
749+
* See https://docs.djangoproject.com/en/3.1/ref/request-response/#jsonresponse-objects.
750+
*/
751+
module JsonResponse {
752+
/** Gets a reference to the `django.http.response.JsonResponse` class. */
753+
private DataFlow::Node classRef(DataFlow::TypeTracker t) {
754+
t.start() and
755+
result = response_attr("JsonResponse")
756+
or
757+
// TODO: remove/expand this part of the template as needed
758+
// Handle `http.JsonResponse` alias
759+
t.start() and
760+
result = http_attr("JsonResponse")
761+
or
762+
exists(DataFlow::TypeTracker t2 | result = classRef(t2).track(t2, t))
763+
}
764+
765+
/** Gets a reference to the `django.http.response.JsonResponse` class. */
766+
DataFlow::Node classRef() { result = classRef(DataFlow::TypeTracker::end()) }
767+
768+
/**
769+
* A source of an instance of `django.http.response.JsonResponse`.
770+
*
771+
* This can include instantiation of the class, return value from function
772+
* calls, or a special parameter that will be set when functions are call by external
773+
* library.
774+
*
775+
* Use `JsonResponse::instance()` predicate to get references to instances of `django.http.response.JsonResponse`.
776+
*/
777+
abstract class InstanceSource extends HTTP::Server::HttpResponse::Range, DataFlow::Node {
778+
}
779+
780+
/** A direct instantiation of `django.http.response.JsonResponse`. */
781+
private class ClassInstantiation extends InstanceSource, DataFlow::CfgNode {
782+
override CallNode node;
783+
784+
ClassInstantiation() { node.getFunction() = classRef().asCfgNode() }
785+
786+
override DataFlow::Node getBody() {
787+
result.asCfgNode() in [node.getArg(0), node.getArgByName("content")]
788+
}
789+
790+
// How to support the `headers` argument here?
791+
override DataFlow::Node getMimetypeOrContentTypeArg() { none() }
792+
793+
override string getMimetypeDefault() { result = "application/json" }
794+
}
795+
796+
/** Gets a reference to an instance of `django.http.response.JsonResponse`. */
797+
private DataFlow::Node instance(DataFlow::TypeTracker t) {
798+
t.start() and
799+
result instanceof InstanceSource
800+
or
801+
exists(DataFlow::TypeTracker t2 | result = instance(t2).track(t2, t))
802+
}
803+
804+
/** Gets a reference to an instance of `django.http.response.JsonResponse`. */
805+
DataFlow::Node instance() { result = instance(DataFlow::TypeTracker::end()) }
806+
}
742807
}
743808
}
744809
}

python/ql/test/experimental/library-tests/frameworks/django-v1/response_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# FP reported in https://github.com/github/codeql-python-team/issues/38
55
def safe__json_response(request):
66
# implicitly sets Content-Type to "application/json"
7-
return JsonResponse({"foo": request.GET.get("foo")}) # $f-:HttpResponse $f-:mimetype=application/json $f-:responseBody={"foo": request.GET.get("foo")}
7+
return JsonResponse({"foo": request.GET.get("foo")}) # $HttpResponse $mimetype=application/json $responseBody=Dict
88

99
# Not an XSS sink, since the Content-Type is not "text/html"
1010
def safe__manual_json_response(request):

0 commit comments

Comments
 (0)