Merge branch 'master' into python-autoformat-almost-everything

This commit is contained in:
Taus Brock-Nannestad
2020-03-30 12:24:01 +02:00
239 changed files with 17972 additions and 15133 deletions

View File

@@ -0,0 +1,7 @@
| test.py:10:15:10:17 | ControlFlowNode for cls | class Foo |
| test.py:17:15:17:17 | ControlFlowNode for cls | class Foo |
| test.py:17:15:17:17 | ControlFlowNode for cls | self instance of Foo |
| test.py:22:15:22:17 | ControlFlowNode for cls | class Foo |
| test.py:22:15:22:17 | ControlFlowNode for cls | self instance of Foo |
| test.py:27:15:27:17 | ControlFlowNode for cls | class Foo |
| test.py:27:15:27:17 | ControlFlowNode for cls | self instance of Foo |

View File

@@ -0,0 +1,10 @@
import python
from NameNode name, CallNode call, string debug
where
call.getAnArg() = name and
call.getFunction().(NameNode).getId() = "check" and
if exists(name.pointsTo())
then debug = name.pointsTo().toString()
else debug = "<MISSING pointsTo()>"
select name, debug

View File

@@ -0,0 +1,35 @@
# See https://github.com/Semmle/ql/issues/3113
def some_decorator(func):
print("this could be tricky for our analysis")
return func
class Foo(object):
@classmethod
def no_problem(cls):
check(cls) # analysis says 'cls' can only point-to Class Foo
@some_decorator
@classmethod
def problem_through_instance(cls):
# Problem is that our analysis says that 'cls' can point to EITHER the
# Class Foo (correct) or an instance of Foo (wrong)
check(cls)
@some_decorator
@classmethod
def problem_through_class(cls):
check(cls) # same as above
@classmethod
@some_decorator
def also_problem(cls):
check(cls) # same as above
# We need to call the methods before our analysis works
f1 = Foo()
f1.no_problem()
f1.problem_through_instance()
f1.also_problem()
Foo.problem_through_class()

View File

@@ -0,0 +1,17 @@
| fabric_v1_test.py:8:7:8:28 | FabricV1Commands | externally controlled string |
| fabric_v1_test.py:9:5:9:27 | FabricV1Commands | externally controlled string |
| fabric_v1_test.py:10:6:10:38 | FabricV1Commands | externally controlled string |
| fabric_v2_test.py:10:16:10:25 | InvokeContextRun | externally controlled string |
| fabric_v2_test.py:12:15:12:36 | InvokeContextRun | externally controlled string |
| fabric_v2_test.py:16:45:16:54 | FabricGroupRun | externally controlled string |
| fabric_v2_test.py:21:10:21:13 | FabricGroupRun | externally controlled string |
| fabric_v2_test.py:31:14:31:41 | InvokeContextRun | externally controlled string |
| fabric_v2_test.py:33:15:33:64 | InvokeContextRun | externally controlled string |
| invoke_test.py:8:12:8:21 | InvokeRun | externally controlled string |
| invoke_test.py:9:20:9:40 | InvokeRun | externally controlled string |
| invoke_test.py:12:17:12:24 | InvokeRun | externally controlled string |
| invoke_test.py:13:25:13:32 | InvokeRun | externally controlled string |
| invoke_test.py:17:11:17:40 | InvokeContextRun | externally controlled string |
| invoke_test.py:21:11:21:32 | InvokeContextRun | externally controlled string |
| invoke_test.py:27:11:27:25 | InvokeContextRun | externally controlled string |
| invoke_test.py:32:11:32:25 | InvokeContextRun | externally controlled string |

View File

@@ -0,0 +1,7 @@
import python
import semmle.python.security.injection.Command
import semmle.python.security.strings.Untrusted
from CommandSink sink, TaintKind kind
where sink.sinks(kind)
select sink, kind

View File

@@ -0,0 +1,22 @@
Copyright (c) 2020 Jeff Forcier.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,10 @@
"""tests for the 'fabric' package (v1.x)
See http://docs.fabfile.org/en/1.14/tutorial.html
"""
from fabric.api import run, local, sudo
local('echo local execution')
run('echo remote execution')
sudo('echo remote execution with sudo')

View File

@@ -0,0 +1,33 @@
"""tests for the 'fabric' package (v2.x)
Most of these examples are taken from the fabric documentation: http://docs.fabfile.org/en/2.5/getting-started.html
See fabric-LICENSE for its' license.
"""
from fabric import Connection
c = Connection('web1')
result = c.run('uname -s')
c.run(command='echo run with kwargs')
from fabric import SerialGroup as Group
results = Group('web1', 'web2', 'mac1').run('uname -s')
from fabric import SerialGroup as Group
pool = Group('web1', 'web2', 'web3')
pool.run('ls')
# using the 'fab' command-line tool
from fabric import task
@task
def upload_and_unpack(c):
if c.run('test -f /opt/mydata/myfile', warn=True).failed:
c.put('myfiles.tgz', '/opt/mydata')
c.run('tar -C /opt/mydata -xzvf /opt/mydata/myfiles.tgz')

View File

@@ -0,0 +1,32 @@
"""tests for the 'invoke' package
see https://www.pyinvoke.org/
"""
import invoke
invoke.run('echo run')
invoke.run(command='echo run with kwarg')
def with_sudo():
invoke.sudo('whoami')
invoke.sudo(command='whoami')
def manual_context():
c = invoke.Context()
c.run('echo run from manual context')
manual_context()
def foo_helper(c):
c.run('echo from foo_helper')
# for use with the 'invoke' command-line tool
@invoke.task
def foo(c):
# 'c' is a invoke.context.Context
c.run('echo task foo')
foo_helper(c)
@invoke.task()
def bar(c):
c.run('echo task bar')

View File

@@ -0,0 +1 @@
semmle-extractor-options: --max-import-depth=2 -p ../../../query-tests/Security/lib/

View File

@@ -26,6 +26,9 @@
| Taint [externally controlled string] | test.py:29 | test.py:29:9:29:25 | Subscript | | --> | Taint [externally controlled string] | test.py:32 | test.py:32:16:32:16 | c | |
| Taint [externally controlled string] | test.py:30 | test.py:30:9:30:20 | tainted_list | | --> | Taint [externally controlled string] | test.py:30 | test.py:30:9:30:27 | Attribute() | |
| Taint [externally controlled string] | test.py:30 | test.py:30:9:30:27 | Attribute() | | --> | Taint [externally controlled string] | test.py:32 | test.py:32:19:32:19 | d | |
| Taint [externally controlled string] | test.py:31 | test.py:31:15:31:26 | tainted_list | | --> | Taint externally controlled string | test.py:32 | test.py:32:22:32:22 | e | |
| Taint [externally controlled string] | test.py:31 | test.py:31:15:31:26 | tainted_list | | --> | Taint externally controlled string | test.py:32 | test.py:32:25:32:25 | f | |
| Taint [externally controlled string] | test.py:31 | test.py:31:15:31:26 | tainted_list | | --> | Taint externally controlled string | test.py:32 | test.py:32:28:32:28 | g | |
| Taint [externally controlled string] | test.py:33 | test.py:33:14:33:25 | tainted_list | | --> | Taint externally controlled string | test.py:33 | test.py:33:5:33:26 | For | |
| Taint [externally controlled string] | test.py:35 | test.py:35:14:35:35 | reversed() | | --> | Taint externally controlled string | test.py:35 | test.py:35:5:35:36 | For | |
| Taint [externally controlled string] | test.py:35 | test.py:35:23:35:34 | tainted_list | | --> | Taint [externally controlled string] | test.py:35 | test.py:35:14:35:35 | reversed() | |

View File

@@ -10,9 +10,9 @@
| test.py:32 | test_access | b | externally controlled string |
| test.py:32 | test_access | c | [externally controlled string] |
| test.py:32 | test_access | d | [externally controlled string] |
| test.py:32 | test_access | e | NO TAINT |
| test.py:32 | test_access | f | NO TAINT |
| test.py:32 | test_access | g | NO TAINT |
| test.py:32 | test_access | e | externally controlled string |
| test.py:32 | test_access | f | externally controlled string |
| test.py:32 | test_access | g | externally controlled string |
| test.py:34 | test_access | h | externally controlled string |
| test.py:36 | test_access | i | externally controlled string |
| test.py:43 | test_dict_access | a | externally controlled string |

View File

@@ -1,7 +1,7 @@
| test.py:13 | test_basic | a | externally controlled string |
| test.py:13 | test_basic | b | externally controlled string |
| test.py:13 | test_basic | c | externally controlled string |
| test.py:13 | test_basic | d | NO TAINT |
| test.py:13 | test_basic | d | externally controlled string |
| test.py:13 | test_basic | urlsplit_res | [externally controlled string] |
| test.py:19 | test_sanitizer | Attribute | externally controlled string |
| test.py:22 | test_sanitizer | Attribute | NO TAINT |

View File

@@ -1,8 +1,35 @@
| Taint [[externally controlled string]] | test.py:19 | test.py:19:10:19:18 | List | | --> | Taint [[externally controlled string]] | test.py:22 | test.py:22:28:22:29 | ll | |
| Taint [[externally controlled string]] | test.py:19 | test.py:19:10:19:18 | List | | --> | Taint [[externally controlled string]] | test.py:26 | test.py:26:28:26:29 | ll | |
| Taint [[externally controlled string]] | test.py:19 | test.py:19:10:19:18 | List | | --> | Taint [[externally controlled string]] | test.py:30 | test.py:30:28:30:29 | ll | |
| Taint [[externally controlled string]] | test.py:22 | test.py:22:28:22:29 | ll | | --> | Taint [externally controlled string] | test.py:23 | test.py:23:22:23:22 | b | |
| Taint [[externally controlled string]] | test.py:22 | test.py:22:28:22:29 | ll | | --> | Taint [externally controlled string] | test.py:23 | test.py:23:25:23:25 | c | |
| Taint [[externally controlled string]] | test.py:22 | test.py:22:28:22:29 | ll | | --> | Taint externally controlled string | test.py:23 | test.py:23:10:23:11 | a1 | |
| Taint [[externally controlled string]] | test.py:22 | test.py:22:28:22:29 | ll | | --> | Taint externally controlled string | test.py:23 | test.py:23:14:23:15 | a2 | |
| Taint [[externally controlled string]] | test.py:22 | test.py:22:28:22:29 | ll | | --> | Taint externally controlled string | test.py:23 | test.py:23:18:23:19 | a3 | |
| Taint [[externally controlled string]] | test.py:26 | test.py:26:28:26:29 | ll | | --> | Taint [externally controlled string] | test.py:27 | test.py:27:22:27:22 | b | |
| Taint [[externally controlled string]] | test.py:26 | test.py:26:28:26:29 | ll | | --> | Taint [externally controlled string] | test.py:27 | test.py:27:25:27:25 | c | |
| Taint [[externally controlled string]] | test.py:26 | test.py:26:28:26:29 | ll | | --> | Taint externally controlled string | test.py:27 | test.py:27:10:27:11 | a1 | |
| Taint [[externally controlled string]] | test.py:26 | test.py:26:28:26:29 | ll | | --> | Taint externally controlled string | test.py:27 | test.py:27:14:27:15 | a2 | |
| Taint [[externally controlled string]] | test.py:26 | test.py:26:28:26:29 | ll | | --> | Taint externally controlled string | test.py:27 | test.py:27:18:27:19 | a3 | |
| Taint [[externally controlled string]] | test.py:30 | test.py:30:28:30:29 | ll | | --> | Taint [externally controlled string] | test.py:31 | test.py:31:22:31:22 | b | |
| Taint [[externally controlled string]] | test.py:30 | test.py:30:28:30:29 | ll | | --> | Taint [externally controlled string] | test.py:31 | test.py:31:25:31:25 | c | |
| Taint [[externally controlled string]] | test.py:30 | test.py:30:28:30:29 | ll | | --> | Taint externally controlled string | test.py:31 | test.py:31:10:31:11 | a1 | |
| Taint [[externally controlled string]] | test.py:30 | test.py:30:28:30:29 | ll | | --> | Taint externally controlled string | test.py:31 | test.py:31:14:31:15 | a2 | |
| Taint [[externally controlled string]] | test.py:30 | test.py:30:28:30:29 | ll | | --> | Taint externally controlled string | test.py:31 | test.py:31:18:31:19 | a3 | |
| Taint [[externally controlled string]] | test.py:47 | test.py:47:28:47:54 | Tuple | | --> | Taint externally controlled string | test.py:48 | test.py:48:10:48:10 | a | |
| Taint [[externally controlled string]] | test.py:47 | test.py:47:28:47:54 | Tuple | | --> | Taint externally controlled string | test.py:48 | test.py:48:13:48:13 | b | |
| Taint [[externally controlled string]] | test.py:47 | test.py:47:28:47:54 | Tuple | | --> | Taint externally controlled string | test.py:48 | test.py:48:16:48:16 | c | |
| Taint [[externally controlled string]] | test.py:47 | test.py:47:28:47:54 | Tuple | | --> | Taint externally controlled string | test.py:48 | test.py:48:19:48:19 | d | |
| Taint [[externally controlled string]] | test.py:47 | test.py:47:28:47:54 | Tuple | | --> | Taint externally controlled string | test.py:48 | test.py:48:22:48:22 | e | |
| Taint [[externally controlled string]] | test.py:47 | test.py:47:28:47:54 | Tuple | | --> | Taint externally controlled string | test.py:48 | test.py:48:25:48:25 | f | |
| Taint [externally controlled string] | test.py:6 | test.py:6:9:6:20 | TAINTED_LIST | | --> | Taint [externally controlled string] | test.py:7 | test.py:7:15:7:15 | l | |
| Taint [externally controlled string] | test.py:7 | test.py:7:15:7:15 | l | | --> | Taint externally controlled string | test.py:8 | test.py:8:10:8:10 | a | |
| Taint [externally controlled string] | test.py:7 | test.py:7:15:7:15 | l | | --> | Taint externally controlled string | test.py:8 | test.py:8:13:8:13 | b | |
| Taint [externally controlled string] | test.py:7 | test.py:7:15:7:15 | l | | --> | Taint externally controlled string | test.py:8 | test.py:8:16:8:16 | c | |
| Taint [externally controlled string] | test.py:12 | test.py:12:9:12:20 | TAINTED_LIST | | --> | Taint [externally controlled string] | test.py:13 | test.py:13:17:13:17 | l | |
| Taint [externally controlled string] | test.py:13 | test.py:13:17:13:17 | l | | --> | Taint externally controlled string | test.py:14 | test.py:14:10:14:10 | a | |
| Taint [externally controlled string] | test.py:13 | test.py:13:17:13:17 | l | | --> | Taint externally controlled string | test.py:14 | test.py:14:13:14:13 | b | |
| Taint [externally controlled string] | test.py:13 | test.py:13:17:13:17 | l | | --> | Taint externally controlled string | test.py:14 | test.py:14:16:14:16 | c | |
| Taint [externally controlled string] | test.py:18 | test.py:18:9:18:20 | TAINTED_LIST | | --> | Taint [externally controlled string] | test.py:19 | test.py:19:11:19:11 | l | |
| Taint [externally controlled string] | test.py:18 | test.py:18:9:18:20 | TAINTED_LIST | | --> | Taint [externally controlled string] | test.py:19 | test.py:19:14:19:14 | l | |
| Taint [externally controlled string] | test.py:18 | test.py:18:9:18:20 | TAINTED_LIST | | --> | Taint [externally controlled string] | test.py:19 | test.py:19:17:19:17 | l | |

View File

@@ -1,33 +1,33 @@
| test.py:8 | unpacking | a | NO TAINT |
| test.py:8 | unpacking | b | NO TAINT |
| test.py:8 | unpacking | c | NO TAINT |
| test.py:14 | unpacking_to_list | a | NO TAINT |
| test.py:14 | unpacking_to_list | b | NO TAINT |
| test.py:14 | unpacking_to_list | c | NO TAINT |
| test.py:23 | nested | a1 | NO TAINT |
| test.py:23 | nested | a2 | NO TAINT |
| test.py:23 | nested | a3 | NO TAINT |
| test.py:23 | nested | b | NO TAINT |
| test.py:23 | nested | c | NO TAINT |
| test.py:27 | nested | a1 | NO TAINT |
| test.py:27 | nested | a2 | NO TAINT |
| test.py:27 | nested | a3 | NO TAINT |
| test.py:27 | nested | b | NO TAINT |
| test.py:27 | nested | c | NO TAINT |
| test.py:31 | nested | a1 | NO TAINT |
| test.py:31 | nested | a2 | NO TAINT |
| test.py:31 | nested | a3 | NO TAINT |
| test.py:31 | nested | b | NO TAINT |
| test.py:31 | nested | c | NO TAINT |
| test.py:8 | unpacking | a | externally controlled string |
| test.py:8 | unpacking | b | externally controlled string |
| test.py:8 | unpacking | c | externally controlled string |
| test.py:14 | unpacking_to_list | a | externally controlled string |
| test.py:14 | unpacking_to_list | b | externally controlled string |
| test.py:14 | unpacking_to_list | c | externally controlled string |
| test.py:23 | nested | a1 | externally controlled string |
| test.py:23 | nested | a2 | externally controlled string |
| test.py:23 | nested | a3 | externally controlled string |
| test.py:23 | nested | b | [externally controlled string] |
| test.py:23 | nested | c | [externally controlled string] |
| test.py:27 | nested | a1 | externally controlled string |
| test.py:27 | nested | a2 | externally controlled string |
| test.py:27 | nested | a3 | externally controlled string |
| test.py:27 | nested | b | [externally controlled string] |
| test.py:27 | nested | c | [externally controlled string] |
| test.py:31 | nested | a1 | externally controlled string |
| test.py:31 | nested | a2 | externally controlled string |
| test.py:31 | nested | a3 | externally controlled string |
| test.py:31 | nested | b | [externally controlled string] |
| test.py:31 | nested | c | [externally controlled string] |
| test.py:38 | unpack_from_set | a | NO TAINT |
| test.py:38 | unpack_from_set | b | NO TAINT |
| test.py:38 | unpack_from_set | c | NO TAINT |
| test.py:48 | contrived_1 | a | NO TAINT |
| test.py:48 | contrived_1 | b | NO TAINT |
| test.py:48 | contrived_1 | c | NO TAINT |
| test.py:48 | contrived_1 | d | NO TAINT |
| test.py:48 | contrived_1 | e | NO TAINT |
| test.py:48 | contrived_1 | f | NO TAINT |
| test.py:48 | contrived_1 | a | externally controlled string |
| test.py:48 | contrived_1 | b | externally controlled string |
| test.py:48 | contrived_1 | c | externally controlled string |
| test.py:48 | contrived_1 | d | externally controlled string |
| test.py:48 | contrived_1 | e | externally controlled string |
| test.py:48 | contrived_1 | f | externally controlled string |
| test.py:56 | contrived_2 | a | NO TAINT |
| test.py:56 | contrived_2 | b | NO TAINT |
| test.py:56 | contrived_2 | c | NO TAINT |

View File

@@ -0,0 +1,2 @@
| test_1x.py:13:21:13:24 | django.redirect | externally controlled string |
| test_2x_3x.py:13:21:13:24 | django.redirect | externally controlled string |

View File

@@ -0,0 +1,7 @@
import python
import semmle.python.web.HttpRedirect
import semmle.python.security.strings.Untrusted
from HttpRedirectTaintSink sink, TaintKind kind
where sink.sinks(kind)
select sink, kind

View File

@@ -1,7 +1,23 @@
| views.py:7:25:7:63 | django.Response(...) | externally controlled string |
| views.py:11:25:11:52 | django.Response(...) | externally controlled string |
| views.py:15:25:15:53 | django.Response(...) | externally controlled string |
| views.py:23:29:23:60 | django.Response(...) | externally controlled string |
| views.py:29:29:29:65 | django.Response(...) | externally controlled string |
| views.py:34:25:34:63 | django.Response(...) | externally controlled string |
| views.py:38:25:38:70 | django.Response(...) | externally controlled string |
| views_1x.py:8:25:8:63 | django.Response(...) | externally controlled string |
| views_1x.py:12:25:12:52 | django.Response(...) | externally controlled string |
| views_1x.py:16:25:16:53 | django.Response(...) | externally controlled string |
| views_1x.py:21:15:21:42 | django.Response.write(...) | externally controlled string |
| views_1x.py:30:29:30:60 | django.Response(...) | externally controlled string |
| views_1x.py:36:29:36:65 | django.Response(...) | externally controlled string |
| views_1x.py:41:25:41:63 | django.Response(...) | externally controlled string |
| views_1x.py:45:25:45:70 | django.Response(...) | externally controlled string |
| views_1x.py:66:25:66:55 | django.Response(...) | externally controlled string |
| views_1x.py:75:25:75:33 | django.Response(...) | externally controlled string |
| views_2x_3x.py:8:25:8:63 | django.Response(...) | externally controlled string |
| views_2x_3x.py:12:25:12:52 | django.Response(...) | externally controlled string |
| views_2x_3x.py:16:25:16:53 | django.Response(...) | externally controlled string |
| views_2x_3x.py:21:15:21:42 | django.Response.write(...) | externally controlled string |
| views_2x_3x.py:30:29:30:60 | django.Response(...) | externally controlled string |
| views_2x_3x.py:36:29:36:65 | django.Response(...) | externally controlled string |
| views_2x_3x.py:41:25:41:63 | django.Response(...) | externally controlled string |
| views_2x_3x.py:45:25:45:70 | django.Response(...) | externally controlled string |
| views_2x_3x.py:66:25:66:40 | django.Response(...) | externally controlled string |
| views_2x_3x.py:79:25:79:61 | django.Response(...) | externally controlled string |
| views_2x_3x.py:82:25:82:69 | django.Response(...) | externally controlled string |
| views_2x_3x.py:85:25:85:64 | django.Response(...) | externally controlled string |
| views_2x_3x.py:88:25:88:32 | django.Response(...) | externally controlled string |

View File

@@ -1,19 +1,51 @@
| test.py:5:19:5:25 | request | django.request.HttpRequest |
| test.py:5:28:5:31 | path | externally controlled string |
| test.py:11:19:11:25 | request | django.request.HttpRequest |
| test.py:11:28:11:31 | path | externally controlled string |
| views.py:6:19:6:25 | request | django.request.HttpRequest |
| views.py:6:28:6:30 | foo | externally controlled string |
| views.py:6:33:6:35 | bar | externally controlled string |
| views.py:10:20:10:26 | request | django.request.HttpRequest |
| views.py:14:21:14:27 | request | django.request.HttpRequest |
| views.py:22:20:22:26 | request | django.request.HttpRequest |
| views.py:28:19:28:25 | request | django.request.HttpRequest |
| views.py:32:19:32:25 | request | django.request.HttpRequest |
| views.py:32:28:32:38 | page_number | externally controlled string |
| views.py:37:24:37:30 | request | django.request.HttpRequest |
| views.py:37:33:37:36 | arg0 | externally controlled string |
| views.py:37:39:37:42 | arg1 | externally controlled string |
| views.py:57:15:57:21 | request | django.request.HttpRequest |
| views.py:57:24:57:31 | username | externally controlled string |
| views.py:66:30:66:36 | request | django.request.HttpRequest |
| test_1x.py:6:19:6:25 | request | django.request.HttpRequest |
| test_1x.py:6:28:6:31 | path | externally controlled string |
| test_1x.py:12:19:12:25 | request | django.request.HttpRequest |
| test_1x.py:12:28:12:31 | path | externally controlled string |
| test_2x_3x.py:6:19:6:25 | request | django.request.HttpRequest |
| test_2x_3x.py:6:28:6:31 | path | externally controlled string |
| test_2x_3x.py:12:19:12:25 | request | django.request.HttpRequest |
| test_2x_3x.py:12:28:12:31 | path | externally controlled string |
| views_1x.py:7:19:7:25 | request | django.request.HttpRequest |
| views_1x.py:7:28:7:30 | foo | externally controlled string |
| views_1x.py:7:33:7:35 | bar | externally controlled string |
| views_1x.py:11:20:11:26 | request | django.request.HttpRequest |
| views_1x.py:15:21:15:27 | request | django.request.HttpRequest |
| views_1x.py:19:21:19:27 | request | django.request.HttpRequest |
| views_1x.py:29:20:29:26 | request | django.request.HttpRequest |
| views_1x.py:29:29:29:37 | untrusted | externally controlled string |
| views_1x.py:35:19:35:25 | request | django.request.HttpRequest |
| views_1x.py:35:28:35:36 | untrusted | externally controlled string |
| views_1x.py:39:19:39:25 | request | django.request.HttpRequest |
| views_1x.py:39:28:39:38 | page_number | externally controlled string |
| views_1x.py:44:24:44:30 | request | django.request.HttpRequest |
| views_1x.py:44:33:44:36 | arg0 | externally controlled string |
| views_1x.py:44:39:44:42 | arg1 | externally controlled string |
| views_1x.py:65:15:65:21 | request | django.request.HttpRequest |
| views_1x.py:65:24:65:31 | username | externally controlled string |
| views_1x.py:74:13:74:19 | request | django.request.HttpRequest |
| views_2x_3x.py:7:19:7:25 | request | django.request.HttpRequest |
| views_2x_3x.py:7:28:7:30 | foo | externally controlled string |
| views_2x_3x.py:7:33:7:35 | bar | externally controlled string |
| views_2x_3x.py:11:20:11:26 | request | django.request.HttpRequest |
| views_2x_3x.py:15:21:15:27 | request | django.request.HttpRequest |
| views_2x_3x.py:19:21:19:27 | request | django.request.HttpRequest |
| views_2x_3x.py:29:20:29:26 | request | django.request.HttpRequest |
| views_2x_3x.py:29:29:29:37 | untrusted | externally controlled string |
| views_2x_3x.py:35:19:35:25 | request | django.request.HttpRequest |
| views_2x_3x.py:35:28:35:36 | untrusted | externally controlled string |
| views_2x_3x.py:39:19:39:25 | request | django.request.HttpRequest |
| views_2x_3x.py:39:28:39:38 | page_number | externally controlled string |
| views_2x_3x.py:44:24:44:30 | request | django.request.HttpRequest |
| views_2x_3x.py:44:33:44:36 | arg0 | externally controlled string |
| views_2x_3x.py:44:39:44:42 | arg1 | externally controlled string |
| views_2x_3x.py:78:17:78:23 | request | django.request.HttpRequest |
| views_2x_3x.py:78:26:78:36 | page_number | externally controlled string |
| views_2x_3x.py:81:17:81:23 | request | django.request.HttpRequest |
| views_2x_3x.py:81:26:81:28 | foo | externally controlled string |
| views_2x_3x.py:81:31:81:33 | bar | externally controlled string |
| views_2x_3x.py:81:36:81:38 | baz | externally controlled string |
| views_2x_3x.py:84:17:84:23 | request | django.request.HttpRequest |
| views_2x_3x.py:84:26:84:28 | foo | externally controlled string |
| views_2x_3x.py:84:31:84:33 | bar | externally controlled string |
| views_2x_3x.py:87:26:87:32 | request | django.request.HttpRequest |

View File

@@ -1,3 +1,4 @@
"""tests for Django 1.x"""
from django.conf.urls import url
from django.shortcuts import redirect, render

View File

@@ -0,0 +1,19 @@
"""tests for Django 2.x and 3.x"""
from django.urls import path
from django.shortcuts import redirect, render
def with_template(request, path='default'):
env = {'path': path}
# We would need to understand django templates to know if this is safe or not
return render(request, 'possibly-vulnerable-template.html', env)
def vuln_redirect(request, path):
return redirect(path)
urlpatterns = [
path('/<path>', with_template),
path('/redirect/<path>', vuln_redirect),
]

View File

@@ -1,3 +1,4 @@
"""test of views for Django 1.x"""
from django.conf.urls import patterns, url
from django.http.response import HttpResponse
from django.views.generic import View
@@ -15,16 +16,22 @@ def post_params_xss(request):
return HttpResponse(request.POST.get("untrusted"))
def http_resp_write(request):
rsp = HttpResponse()
rsp.write(request.GET.get("untrusted"))
return rsp
class Foo(object):
# Note: since Foo is used as the super type in a class view, it will be able to handle requests.
# TODO: Currently we don't flag `untrusted` as a DjangoRequestParameter
def post(self, request, untrusted):
return HttpResponse('Foo post: {}'.format(untrusted))
class ClassView(View, Foo):
# TODO: Currently we don't flag `untrusted` as a DjangoRequestParameter
def get(self, request, untrusted):
return HttpResponse('ClassView get: {}'.format(untrusted))
@@ -42,6 +49,7 @@ urlpatterns = [
url(r'^url_match/(?P<foo>[^/]+)/(?P<bar>[^/]+)$', url_match_xss),
url(r'^get_params$', get_params_xss),
url(r'^post_params$', post_params_xss),
url(r'^http_resp_write$', http_resp_write),
url(r'^class_view/(?P<untrusted>.+)$', ClassView.as_view()),
# one pattern to support `articles/page-<n>` and ensuring that articles/ goes to page-1
@@ -51,22 +59,21 @@ urlpatterns = [
url(r'^([^/]+)/(?:foo|bar)/([^/]+)$', xxs_positional_arg, name='xxs_positional_arg'),
]
################################################################################
# Using patterns() for routing
def show_user(request, username):
pass
return HttpResponse('show_user {}'.format(username))
urlpatterns = patterns(url(r'^users/(?P<username>[^/]+)$', show_user))
################################################################################
# Show we understand the keyword arguments to django.conf.urls.url
def we_understand_url_kwargs(request):
pass
def kw_args(request):
return HttpResponse('kw_args')
urlpatterns = [
url(view=we_understand_url_kwargs, regex=r'^specifying-as-kwargs-is-not-a-problem$')
url(view=kw_args, regex=r'^kw_args$')
]

View File

@@ -0,0 +1,122 @@
"""testing views for Django 2.x and 3.x"""
from django.urls import path, re_path
from django.http import HttpResponse
from django.views import View
def url_match_xss(request, foo, bar, no_taint=None):
return HttpResponse('url_match_xss: {} {}'.format(foo, bar))
def get_params_xss(request):
return HttpResponse(request.GET.get("untrusted"))
def post_params_xss(request):
return HttpResponse(request.POST.get("untrusted"))
def http_resp_write(request):
rsp = HttpResponse()
rsp.write(request.GET.get("untrusted"))
return rsp
class Foo(object):
# Note: since Foo is used as the super type in a class view, it will be able to handle requests.
def post(self, request, untrusted):
return HttpResponse('Foo post: {}'.format(untrusted))
class ClassView(View, Foo):
def get(self, request, untrusted):
return HttpResponse('ClassView get: {}'.format(untrusted))
def show_articles(request, page_number=1):
page_number = int(page_number)
return HttpResponse('articles page: {}'.format(page_number))
def xxs_positional_arg(request, arg0, arg1, no_taint=None):
return HttpResponse('xxs_positional_arg: {} {}'.format(arg0, arg1))
urlpatterns = [
re_path(r'^url_match/(?P<foo>[^/]+)/(?P<bar>[^/]+)$', url_match_xss),
re_path(r'^get_params$', get_params_xss),
re_path(r'^post_params$', post_params_xss),
re_path(r'^http_resp_write$', http_resp_write),
re_path(r'^class_view/(?P<untrusted>.+)$', ClassView.as_view()),
# one pattern to support `articles/page-<n>` and ensuring that articles/ goes to page-1
re_path(r'articles/^(?:page-(?P<page_number>\d+)/)?$', show_articles),
# passing as positional argument is not the recommended way of doing things, but it is certainly
# possible
re_path(r'^([^/]+)/(?:foo|bar)/([^/]+)$', xxs_positional_arg, name='xxs_positional_arg'),
]
# Show we understand the keyword arguments to from django.urls.re_path
def re_path_kwargs(request):
return HttpResponse('re_path_kwargs')
urlpatterns = [
re_path(view=re_path_kwargs, regex=r'^specifying-as-kwargs-is-not-a-problem$')
]
################################################################################
# Using path
################################################################################
# saying page_number is an externally controlled *string* is a bit strange, when we have an int converter :O
def page_number(request, page_number=1):
return HttpResponse('page_number: {}'.format(page_number))
def foo_bar_baz(request, foo, bar, baz):
return HttpResponse('foo_bar_baz: {} {} {}'.format(foo, bar, baz))
def path_kwargs(request, foo, bar):
return HttpResponse('path_kwargs: {} {} {}'.format(foo, bar))
def not_valid_identifier(request):
return HttpResponse('<foo!>')
urlpatterns = [
path('articles/', page_number),
path('articles/page-<int:page_number>', page_number),
path('<int:foo>/<str:bar>/<baz>', foo_bar_baz, name='foo-bar-baz'),
path(view=path_kwargs, route='<foo>/<bar>'),
# We should not report there is a request parameter called `not_valid!`
path('not_valid/<not_valid!>', not_valid_identifier),
]
################################################################################
# We should abort if a decorator is used. As demonstrated below, anything might happen
# def reverse_kwargs(f):
# @wraps(f)
# def f_(*args, **kwargs):
# new_kwargs = dict()
# for key, value in kwargs.items():
# new_kwargs[key[::-1]] = value
# return f(*args, **new_kwargs)
# return f_
# @reverse_kwargs
# def decorators_can_do_anything(request, oof, foo=None):
# return HttpResponse('This is a mess'[::-1])
# urlpatterns = [
# path('rev/<foo>', decorators_can_do_anything),
# ]