mirror of
https://github.com/github/codeql.git
synced 2026-04-29 18:55:14 +02:00
Python: Implement routed parameter for django.urls.path
Matching current implementation in
f07a7bf8cf/python/ql/src/semmle/python/web/django/General.qll (L125-L133)
This commit is contained in:
@@ -160,6 +160,34 @@ private module Django {
|
||||
result = djangoRouteHandlerFunctionTracker(DataFlow::TypeTracker::end(), func)
|
||||
}
|
||||
|
||||
/**
|
||||
* A function that is used as a django route handler.
|
||||
*/
|
||||
private class DjangoRouteHandler extends Function {
|
||||
DjangoRouteHandler() { exists(djangoRouteHandlerFunctionTracker(this)) }
|
||||
|
||||
/** Gets the index of the request parameter. */
|
||||
int getRequestParamIndex() {
|
||||
not this.isMethod() and
|
||||
result = 0
|
||||
or
|
||||
this.isMethod() and
|
||||
result = 1
|
||||
}
|
||||
|
||||
/** Gets the request parameter. */
|
||||
Parameter getRequestParam() { result = this.getArg(this.getRequestParamIndex()) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the regex that is used by django to find routed parameters when using `django.urls.path`.
|
||||
*
|
||||
* Taken from https://github.com/django/django/blob/7d1bf29977bb368d7c28e7c6eb146db3b3009ae7/django/urls/resolvers.py#L199
|
||||
*/
|
||||
private string pathRoutedParameterRegex() {
|
||||
result = "<(?:(?<converter>[^>:]+):)?(?<parameter>\\w+)>"
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `django.urls.path`.
|
||||
*
|
||||
@@ -174,14 +202,31 @@ private module Django {
|
||||
result.asCfgNode() = [node.getArg(0), node.getArgByName("route")]
|
||||
}
|
||||
|
||||
override Function getARouteHandler() {
|
||||
override DjangoRouteHandler getARouteHandler() {
|
||||
exists(DataFlow::Node viewArg |
|
||||
viewArg.asCfgNode() in [node.getArg(1), node.getArgByName("view")] and
|
||||
djangoRouteHandlerFunctionTracker(result) = viewArg
|
||||
)
|
||||
}
|
||||
|
||||
override Parameter getARoutedParameter() { none() }
|
||||
override Parameter getARoutedParameter() {
|
||||
// If we don't know the URL pattern, we simply mark all parameters as a routed
|
||||
// parameter. This should give us more RemoteFlowSources but could also lead to
|
||||
// more FPs. If this turns out to be the wrong tradeoff, we can always change our mind.
|
||||
exists(DjangoRouteHandler routeHandler | routeHandler = this.getARouteHandler() |
|
||||
not exists(this.getUrlPattern()) and
|
||||
result in [routeHandler.getArg(_), routeHandler.getArgByName(_)] and
|
||||
not result = any(int i | i <= routeHandler.getRequestParamIndex() | routeHandler.getArg(i))
|
||||
)
|
||||
or
|
||||
exists(string name |
|
||||
result = this.getARouteHandler().getArgByName(name) and
|
||||
exists(string match |
|
||||
match = this.getUrlPattern().regexpFind(pathRoutedParameterRegex(), _, _) and
|
||||
name = match.regexpCapture(pathRoutedParameterRegex(), 2)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -198,7 +243,7 @@ private module Django {
|
||||
result.asCfgNode() = [node.getArg(0), node.getArgByName("route")]
|
||||
}
|
||||
|
||||
override Function getARouteHandler() {
|
||||
override DjangoRouteHandler getARouteHandler() {
|
||||
exists(DataFlow::Node viewArg |
|
||||
viewArg.asCfgNode() in [node.getArg(1), node.getArgByName("view")] and
|
||||
djangoRouteHandlerFunctionTracker(result) = viewArg
|
||||
|
||||
@@ -3,13 +3,5 @@
|
||||
| routing_test.py:39:45:39:88 | Comment # $routeHandler $routedParameter=page_number | Missing result:routedParameter=page_number |
|
||||
| routing_test.py:44:62:44:120 | Comment # $routeHandler $routedParameter=arg0 $routedParameter=arg1 | Missing result:routedParameter=arg0 |
|
||||
| routing_test.py:44:62:44:120 | Comment # $routeHandler $routedParameter=arg0 $routedParameter=arg1 | Missing result:routedParameter=arg1 |
|
||||
| routing_test.py:78:43:78:86 | Comment # $routeHandler $routedParameter=page_number | Missing result:routedParameter=page_number |
|
||||
| routing_test.py:81:43:81:120 | Comment # $routeHandler $routedParameter=foo $routedParameter=bar $routedParameter=baz | Missing result:routedParameter=bar |
|
||||
| routing_test.py:81:43:81:120 | Comment # $routeHandler $routedParameter=foo $routedParameter=bar $routedParameter=baz | Missing result:routedParameter=baz |
|
||||
| routing_test.py:81:43:81:120 | Comment # $routeHandler $routedParameter=foo $routedParameter=bar $routedParameter=baz | Missing result:routedParameter=foo |
|
||||
| routing_test.py:84:38:84:94 | Comment # $routeHandler $routedParameter=foo $routedParameter=bar | Missing result:routedParameter=bar |
|
||||
| routing_test.py:84:38:84:94 | Comment # $routeHandler $routedParameter=foo $routedParameter=bar | Missing result:routedParameter=foo |
|
||||
| taint_test.py:6:60:6:116 | Comment # $routeHandler $routedParameter=foo $routedParameter=bar | Missing result:routedParameter=bar |
|
||||
| taint_test.py:6:60:6:116 | Comment # $routeHandler $routedParameter=foo $routedParameter=bar | Missing result:routedParameter=foo |
|
||||
| testapp/views.py:3:33:3:47 | Comment # $routeHandler | Missing result:routeHandler= |
|
||||
| testapp/views.py:6:37:6:51 | Comment # $routeHandler | Missing result:routeHandler= |
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
| taint_test.py:7 | fail | test_taint | bar |
|
||||
| taint_test.py:7 | fail | test_taint | foo |
|
||||
| taint_test.py:7 | ok | test_taint | bar |
|
||||
| taint_test.py:7 | ok | test_taint | foo |
|
||||
| taint_test.py:8 | ok | test_taint | baz |
|
||||
| taint_test.py:14 | fail | test_taint | request |
|
||||
| taint_test.py:16 | fail | test_taint | request.body |
|
||||
|
||||
Reference in New Issue
Block a user