Merge branch 'master' into python-fix-multi-assign-points-to

This commit is contained in:
Taus Brock-Nannestad
2020-03-12 18:50:10 +01:00
618 changed files with 15540 additions and 4952 deletions

View File

@@ -1,2 +1 @@
semmle-extractor-options: --lang=2 --max-import-depth=4
optimize: true

View File

@@ -1,2 +1,2 @@
| TruncatedDivision_test.py:8:12:8:16 | BinaryExpr | Result of division may be truncated as its $@ and $@ arguments may both be integers. | TruncatedDivision_test.py:8:12:8:12 | TruncatedDivision_test.py:8 | left | TruncatedDivision_test.py:8:16:8:16 | TruncatedDivision_test.py:8 | right |
| TruncatedDivision_test.py:11:12:11:40 | BinaryExpr | Result of division may be truncated as its $@ and $@ arguments may both be integers. | TruncatedDivision_test.py:2:12:2:12 | TruncatedDivision_test.py:2 | left | TruncatedDivision_test.py:5:12:5:12 | TruncatedDivision_test.py:5 | right |
| TruncatedDivision_test.py:65:7:65:11 | BinaryExpr | Result of division may be truncated as its $@ and $@ arguments may both be integers. | TruncatedDivision_test.py:65:7:65:7 | TruncatedDivision_test.py:65 | left | TruncatedDivision_test.py:65:11:65:11 | TruncatedDivision_test.py:65 | right |
| TruncatedDivision_test.py:72:7:72:35 | BinaryExpr | Result of division may be truncated as its $@ and $@ arguments may both be integers. | TruncatedDivision_test.py:25:12:25:12 | TruncatedDivision_test.py:25 | left | TruncatedDivision_test.py:28:12:28:12 | TruncatedDivision_test.py:28 | right |

View File

@@ -1,24 +1,88 @@
#### TruncatedDivision.ql
# NOTE: The following test case will only work under Python 2.
# Truncated division occurs when two integers are divided. This causes the
# fractional part, if there is one, to be discared. So for example, `2 / 3` will
# evaluate to `0` instead of `0.666...`.
## Negative Cases
# This case is good, and is a minimal obvious case that should be good. It
# SHOULD NOT be found by the query.
print(3.0 / 2.0)
# This case is good, because it explicitly converts the possibly-truncated
# value to an integer. It SHOULD NOT be found by the query.
def return_three():
return 3
def return_two():
return 2
def f1():
return 3 / 2
print(int(return_three() / return_two()))
def f2():
return return_three() / return_two()
def f3(x):
# These cases are good, because `halve` checks the type, and if the type would
# truncate, it explicitly converts to a float first before doing the division.
# These SHOULD NOT be found by the query.
def halve(x):
if isinstance(x, float):
return x / 2
else:
return (1.0 * x) / 2
def f4():
do_stuff(f3(1))
do_stuff(f3(1.0))
print(halve(1))
print(halve(1.0))
def f5():
return int(return_three() / return_two())
# This case is good, because the sum is `3.0`, which is a float, and will not
# truncate. This case SHOULD NOT be found by the query.
print(average([1.0, 2.0]))
## Positive Cases
# This case is bad, and is a minimal obvious case that should be bad. It
# SHOULD be found by the query.
print(3 / 2)
# This case is bad. It uses indirect returns of integers through function calls
# to produce the problem. I
print(return_three() / return_two())
# This case is bad, because the sum is `3`, which is an integer, and will
# truncate when divided by the length `2`. This case SHOULD be found by the
# query.
# NOTE (2020-02-20):
# The current version of the Value/pointsTo API doesn't permit this detection,
# unfortunately, but we preserve this example in the hopes that future
# versions will catch it. That will necessitate changing the expected results.
def average(l):
return sum(l) / len(l)
print(average([1,2]))

View File

@@ -1 +1,2 @@
| UseofApply.py:19:3:19:17 | ControlFlowNode for apply() | Call to the obsolete builtin function 'apply'. |
| expressions_test.py:3:5:3:21 | ControlFlowNode for apply() | Call to the obsolete builtin function 'apply'. |

View File

@@ -0,0 +1,30 @@
#### UseofApply.ql
# Use of the builtin function `apply` is generally considered bad now that the
# ability to destructure lists of arguments is possible, but we should not flag
# cases where the function is merely named `apply` rather than being the actual
# builtin `apply` function.
def useofapply():
def foo():
pass
# Positive Cases
# This use of `apply` is a reference to the builtin function and so SHOULD be
# caught by the query.
apply(foo, [1])
# Negative Cases
# This use of `apply` is a reference to the locally defined function inside of
# `local`, and so SHOULD NOT be caught by the query.
def local():
def apply(f):
pass
apply(foo)([1])

View File

@@ -1 +1 @@
| expressions_test.py:6:12:6:18 | ControlFlowNode for input() | The unsafe built-in function 'input' is used. |
| expressions_test.py:6:12:6:18 | ControlFlowNode for input() | The unsafe built-in function 'input' is used in Python 2. |

View File

@@ -0,0 +1,3 @@
| mwe_failure.py:7:1:7:23 | class MyTest | <MISSING BASE TYPE> |
| mwe_failure_2.py:7:1:7:23 | class MyTest | <MISSING BASE TYPE> |
| mwe_success.py:7:1:7:23 | class MyTest | class TestCase |

View File

@@ -0,0 +1,10 @@
import python
// as used in semmle.python.filters.Tests
from ClassValue c, string base
where
c.getScope().getLocation().getFile().getShortName().matches("mwe%.py") and
c.getName() = "MyTest" and
if exists(c.getABaseType()) then base = c.getABaseType().toString() else base = "<MISSING BASE TYPE>"
select c, base

View File

@@ -0,0 +1,10 @@
import subprocess
assert subprocess.call(['run-backup']) == 0
class TestCase:
pass
class MyTest(TestCase):
pass
# found by /home/rasmus/code/ql/python/ql/test/query-tests/Statements/asserts/AssertLiteralConstant.qlref

View File

@@ -0,0 +1,8 @@
import subprocess
assert subprocess.call(['run-backup'])
class TestCase:
pass
class MyTest(TestCase):
pass

View File

@@ -0,0 +1,8 @@
import subprocess
subprocess.call(['run-backup'])
class TestCase:
pass
class MyTest(TestCase):
pass

View File

@@ -0,0 +1 @@
semmle-extractor-options: --lang=3 --max-import-depth=1

View File

@@ -1,2 +1 @@
semmle-extractor-options: --lang=3 -p ../../lib/ --max-import-depth=3
optimize: true

View File

@@ -1,2 +1 @@
semmle-extractor-options: --lang=3 --max-import-depth=4
optimize: true

View File

@@ -1,9 +1,9 @@
| test.py:11 | extended_unpacking | first | externally controlled string |
| test.py:11 | extended_unpacking | last | externally controlled string |
| test.py:11 | extended_unpacking | rest | [externally controlled string] |
| test.py:16 | also_allowed | a | [externally controlled string] |
| test.py:11 | extended_unpacking | first | NO TAINT |
| test.py:11 | extended_unpacking | last | NO TAINT |
| test.py:11 | extended_unpacking | rest | NO TAINT |
| test.py:16 | also_allowed | a | NO TAINT |
| test.py:24 | also_allowed | b | NO TAINT |
| test.py:24 | also_allowed | c | NO TAINT |
| test.py:31 | nested | x | externally controlled string |
| test.py:31 | nested | xs | [externally controlled string] |
| test.py:31 | nested | ys | [externally controlled string] |
| test.py:31 | nested | x | NO TAINT |
| test.py:31 | nested | xs | NO TAINT |
| test.py:31 | nested | ys | NO TAINT |

View File

@@ -0,0 +1,30 @@
#### UseofApply.ql
# Use of the builtin function `apply` is generally considered bad now that the
# ability to destructure lists of arguments is possible, but we should not flag
# cases where the function is merely named `apply` rather than being the actual
# builtin `apply` function.
def useofapply():
def foo():
pass
# Positive Cases
# This use of `apply` is a reference to the builtin function and so SHOULD be
# caught by the query.
apply(foo, [1])
# Negative Cases
# This use of `apply` is a reference to the locally defined function inside of
# `local`, and so SHOULD NOT be caught by the query.
def local():
def apply(f):
pass
apply(foo)([1])

View File

@@ -0,0 +1 @@
Expressions/UseofApply.ql

View File

@@ -0,0 +1,7 @@
123456789
223456789
323456789
423456789
5234567ø9
623456789
723456789

View File

@@ -0,0 +1 @@
Imports/EncodingError.ql

View File

@@ -0,0 +1 @@
| bad_encoding.py:11:19:11:19 | Encoding Error | 'utf-8' codec can't decode byte 0x82 in position 82: invalid start byte |

View File

@@ -0,0 +1 @@
Imports/EncodingError.ql

View File

@@ -0,0 +1 @@
| nonsense.py:1:2:1:2 | Syntax Error | Syntax Error (in Python 3.5). |

View File

@@ -0,0 +1 @@
Imports/SyntaxError.ql

View File

@@ -0,0 +1,12 @@
"""Multi-line docstring
"""
# encoding:shift-jis
def f():
print "Python <20>̊J<CC8A><4A><EFBFBD>́A1990 <20>N<EFBFBD><4E><EFBFBD><EFBFBD><EB82A9><EFBFBD>J<EFBFBD>n<EFBFBD><6E><EFBFBD><EFBFBD><EFBFBD>Ă<EFBFBD><C482>܂<EFBFBD>"
"""

View File

@@ -0,0 +1,37 @@
`Twas brillig, and the slithy toves
Did gyre and gimble in the wabe:
All mimsy were the borogoves,
And the mome raths outgrabe.
"Beware the Jabberwock, my son!
The jaws that bite, the claws that catch!
Beware the Jubjub bird, and shun
The frumious Bandersnatch!"
He took his vorpal sword in hand:
Long time the manxome foe he sought --
So rested he by the Tumtum tree,
And stood awhile in thought.
And, as in uffish thought he stood,
The Jabberwock, with eyes of flame,
Came whiffling through the tulgey wood,
And burbled as it came!
One, two! One, two! And through and through
The vorpal blade went snicker-snack!
He left it dead, and with its head
He went galumphing back.
"And, has thou slain the Jabberwock?
Come to my arms, my beamish boy!
O frabjous day! Callooh! Callay!'
He chortled in his joy.
`Twas brillig, and the slithy toves
Did gyre and gimble in the wabe;
All mimsy were the borogoves,
And the mome raths outgrabe.

View File

@@ -0,0 +1 @@
print "Hello World"

View File

@@ -1,2 +1,2 @@
| async_iterator.py:26:11:26:34 | For | $@ of class '$@' may be used in for-loop. | async_iterator.py:26:20:26:33 | ControlFlowNode for MissingAiter() | Non-iterator | async_iterator.py:13:1:13:19 | class MissingAiter | MissingAiter |
| statements_test.py:34:5:34:19 | For | $@ of class '$@' may be used in for-loop. | statements_test.py:34:18:34:18 | ControlFlowNode for IntegerLiteral | Non-iterator | file://:0:0:0:0 | builtin-class int | int |
| async_iterator.py:26:11:26:34 | For | $@ of class '$@' may be used in for-loop. | async_iterator.py:26:20:26:33 | ControlFlowNode for MissingAiter() | Non-iterable | async_iterator.py:13:1:13:19 | class MissingAiter | MissingAiter |
| statements_test.py:34:5:34:19 | For | $@ of class '$@' may be used in for-loop. | statements_test.py:34:18:34:18 | ControlFlowNode for IntegerLiteral | Non-iterable | file://:0:0:0:0 | builtin-class int | int |

View File

@@ -0,0 +1 @@
This directory contains tests for [experimental](../../../../docs/experimental.md) CodeQL queries and libraries.

View File

@@ -1,2 +1 @@
semmle-extractor-options: --max-import-depth=3
optimize: true

View File

@@ -1,2 +1 @@
semmle-extractor-options: --max-import-depth=4
optimize: true

View File

@@ -0,0 +1,3 @@
| test.py:5:7:5:9 | ControlFlowNode for foo | int 42 |
| test.py:11:11:11:13 | ControlFlowNode for foo | int 1 |
| test.py:17:11:17:13 | ControlFlowNode for foo | <MISSING pointsTo()> |

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 @@
semmle-extractor-options: --max-import-depth=1 --lang=3

View File

@@ -0,0 +1,17 @@
# Only a problem in Python 3
from urllib.parse import urlsplit
foo = 42
check(foo)
def func(url):
parts = urlsplit(url)
foo = 1
check(foo)
if parts.path: # using `urlsplit(url).path` here is equivalent
return # using `pass` here instead makes points-to work
foo = 2
check(foo) # no points-to information

View File

@@ -0,0 +1 @@
| test.py:5:7:5:13 | ControlFlowNode for PATTERN | <MISSING pointsTo()> |

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,5 @@
import re
PATTERN = re.compile("a|b")
check(PATTERN)

View File

@@ -1 +0,0 @@
optimize: true

View File

@@ -1,6 +1,6 @@
| 16 | classmethod() | 17 | Function c1 |
| 23 | classmethod() | 20 | Function c2 |
| 24 | classmethod() | 20 | Function c2 |
| 26 | staticmethod() | 27 | Function s1 |
| 33 | staticmethod() | 30 | Function s2 |
| 34 | staticmethod() | 30 | Function s2 |
| 104 | classmethod() | 105 | Function c1 |
| 111 | classmethod() | 108 | Function c2 |
| 112 | classmethod() | 108 | Function c2 |
| 114 | staticmethod() | 115 | Function s1 |
| 121 | staticmethod() | 118 | Function s2 |
| 122 | staticmethod() | 118 | Function s2 |

View File

@@ -1 +1,8 @@
| 6 | Property f | 7 | Function f | 11 | Function f |
| test.py:6:5:6:16 | Function WithDecorator.x | getter | test.py:5:6:5:13 | property x |
| test.py:11:5:11:23 | Function WithDecorator.x | setter | test.py:5:6:5:13 | property x |
| test.py:15:5:15:16 | Function WithDecorator.x | deleter | test.py:5:6:5:13 | property x |
| test.py:21:5:21:16 | Function WithDecoratorOnlyGetter.x | getter | test.py:20:6:20:13 | property x |
| test.py:28:5:28:19 | Function WithoutDecorator.getx | getter | test.py:37:9:37:59 | property getx |
| test.py:31:5:31:26 | Function WithoutDecorator.setx | setter | test.py:37:9:37:59 | property getx |
| test.py:34:5:34:19 | Function WithoutDecorator.delx | deleter | test.py:37:9:37:59 | property getx |
| test.py:41:5:41:19 | Function WithoutDecoratorOnlyGetter.getx | getter | test.py:44:9:44:22 | property getx |

View File

@@ -1,13 +1,11 @@
import python
import semmle.python.types.Descriptors
int lineof(Object o) {
result = o.getOrigin().getLocation().getStartLine()
}
from PropertyObject p, FunctionObject getter, FunctionObject setter
from PropertyValue p, string method_name, FunctionValue method
where
getter = p.getGetter() and setter = p.getSetter()
select lineof(p), p.toString(), lineof(getter), getter.toString(), lineof(setter), setter.toString()
method_name = "getter" and method = p.getGetter()
or
method_name = "setter" and method = p.getSetter()
or
method_name = "deleter" and method = p.getDeleter()
select method, method_name, p

View File

@@ -1,15 +1,103 @@
class C(object):
class WithDecorator(object):
def __init__(self):
self._x = None
@property
def f(self):
return self._f
def x(self):
"""I'm the 'x' property."""
return self._x
@f.setter
def f(self):
return self._f
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
del self._x
class WithDecoratorOnlyGetter(object):
@property
def x(self):
return 42
class WithoutDecorator(object):
def __init__(self):
self._x = None
def getx(self):
return self._x
def setx(self, value):
self._x = value
def delx(self):
del self._x
x = property(getx, setx, delx, "I'm the 'x' property.")
class WithoutDecoratorOnlyGetter(object):
def getx(self):
return 42
x = property(getx)
class WithoutDecoratorOnlyGetterKWArg(object):
def getx(self):
return 42
x = property(fget=getx)
class WithoutDecoratorOnlySetter(object):
def setx(self, value):
self._x = value
x = property(fset=setx) # TODO: Not handled
class WithDecoratorOnlySetter(object):
x = property()
@x.setter
def x(self, value):
print('{} setting value to {}'.format(self.__class__, value))
class FunkyButValid(object):
def delx(self):
print("deleting x")
x = property(fdel=delx)
@x.setter
def y(self, value):
print('setting value to {}'.format(value))
@y.getter
def z(self):
return 42
wat = FunkyButValid()
try:
wat.x
except AttributeError as e:
print("x can't be read")
del wat.x
try:
wat.y
except AttributeError as e:
print("y can't be read")
wat.y = 1234
del wat.y
print(wat.z)
wat.z = 10
del wat.z
class D(object):

View File

@@ -1,2 +1 @@
semmle-extractor-options: -R .
optimize: true

View File

@@ -0,0 +1,5 @@
| file://:0:0:0:0 | Module sys | isUsedAsModule |
| imported.py:0:0:0:0 | Module imported | isUsedAsModule |
| main.py:0:0:0:0 | Module main | isUsedAsScript |
| myscript.py:0:0:0:0 | Script myscript | isUsedAsScript |
| script:0:0:0:0 | Script script | isUsedAsScript |

View File

@@ -0,0 +1,16 @@
import python
from ModuleValue mv, string usage
where
// builtin module has different name in Python 2 and 3
not mv = Module::builtinModule() and
(
mv.isUsedAsModule() and usage = "isUsedAsModule"
or
mv.isUsedAsScript() and usage = "isUsedAsScript"
or
not mv.isUsedAsModule() and
not mv.isUsedAsScript() and
usage = "<UNKNOWN>"
)
select mv, usage

View File

@@ -0,0 +1,6 @@
def func():
pass
if __name__ == "__main__":
print("I could have done something interesting...")
print("but I didn't")

View File

@@ -0,0 +1,5 @@
import imported
if __name__ == "__main__":
imported.func()
print('Done')

View File

@@ -0,0 +1,3 @@
#!/usr/bin/env python
print("I'm actually a script you see ;)")

View File

@@ -0,0 +1 @@
semmle-extractor-options: -F script

View File

@@ -0,0 +1,3 @@
#!/usr/bin/env python
print('Under construction :)')

View File

@@ -1,2 +1 @@
semmle-extractor-options: --max-import-depth=3
optimize: true

View File

@@ -26,9 +26,6 @@
| 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 | externally controlled string |
| test.py:32 | test_access | f | externally controlled string |
| test.py:32 | test_access | g | 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: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

@@ -0,0 +1,7 @@
| UrlsplitUrlparseTempSanitizer | [externally controlled string] | test.py:21 | Pi(urlsplit_res_0) [true] |
| UrlsplitUrlparseTempSanitizer | [externally controlled string] | test.py:24 | Pi(urlsplit_res_3) [true] |
| UrlsplitUrlparseTempSanitizer | [externally controlled string] | test.py:27 | Pi(urlsplit_res_6) [true] |
| UrlsplitUrlparseTempSanitizer | [externally controlled string] | test.py:30 | Pi(urlsplit_res_9) [true] |
| string equality sanitizer | externally controlled string | test.py:21 | Pi(urlsplit_res_0) [true] |
| string equality sanitizer | externally controlled string | test.py:24 | Pi(urlsplit_res_3) [true] |
| string equality sanitizer | externally controlled string | test.py:27 | Pi(urlsplit_res_6) [true] |

View File

@@ -0,0 +1,6 @@
import python
import Taint
from Sanitizer s, TaintKind taint, PyEdgeRefinement test
where s.sanitizingEdge(taint, test)
select s, taint, test.getTest().getLocation().toString(), test.getRepresentation()

View File

@@ -0,0 +1,47 @@
import python
import semmle.python.security.TaintTracking
import semmle.python.security.strings.Untrusted
class SimpleSource extends TaintSource {
SimpleSource() { this.(NameNode).getId() = "TAINTED_STRING" }
override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringKind }
override string toString() { result = "taint source" }
}
class ListSource extends TaintSource {
ListSource() { this.(NameNode).getId() = "TAINTED_LIST" }
override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringSequenceKind }
override string toString() { result = "list taint source" }
}
class DictSource extends TaintSource {
DictSource() { this.(NameNode).getId() = "TAINTED_DICT" }
override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringDictKind }
override string toString() { result = "dict taint source" }
}
class TestConfig extends TaintTracking::Configuration {
TestConfig() { this = "TestConfig" }
override predicate isSanitizer(Sanitizer sanitizer) {
sanitizer instanceof UrlsplitUrlparseTempSanitizer
}
override predicate isSource(TaintTracking::Source source) {
source instanceof SimpleSource
or
source instanceof ListSource
or
source instanceof DictSource
}
override predicate isSink(TaintTracking::Sink sink) {
none()
}
}

View File

@@ -0,0 +1,15 @@
| 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 | urlsplit_res | [externally controlled string] |
| test.py:19 | test_sanitizer | Attribute | externally controlled string |
| test.py:22 | test_sanitizer | Attribute | NO TAINT |
| test.py:25 | test_sanitizer | Subscript | NO TAINT |
| test.py:28 | test_sanitizer | Attribute | NO TAINT |
| test.py:31 | test_sanitizer | Attribute | NO TAINT |
| test.py:34 | test_sanitizer | Attribute | externally controlled string |
| test.py:44 | test_namedtuple | a | NO TAINT |
| test.py:44 | test_namedtuple | b | NO TAINT |
| test.py:44 | test_namedtuple | c | NO TAINT |
| test.py:44 | test_namedtuple | d | NO TAINT |

View File

@@ -0,0 +1,18 @@
import python
import semmle.python.security.TaintTracking
import Taint
from Call call, Expr arg, string taint_string
where
call.getLocation().getFile().getShortName() = "test.py" and
call.getFunc().(Name).getId() = "test" and
arg = call.getAnArg() and
(
not exists(TaintedNode tainted | tainted.getAstNode() = arg) and
taint_string = "NO TAINT"
or
exists(TaintedNode tainted | tainted.getAstNode() = arg |
taint_string = tainted.getTaintKind().toString()
)
)
select arg.getLocation().toString(), call.getScope().(Function).getName(), arg.toString(), taint_string

View File

@@ -0,0 +1,44 @@
from six.moves.urllib.parse import urlsplit
# Currently we don't have support for namedtuples in general, but do have special support
# for `urlsplit` (and `urlparse`)
def test_basic():
tainted_string = TAINTED_STRING
urlsplit_res = urlsplit(tainted_string)
a = urlsplit_res.netloc # field access
b = urlsplit_res.hostname # property
c = urlsplit_res[3] # indexing
_, _, d, _, _ = urlsplit(tainted_string) # unpacking
test(a, b, c, d, urlsplit_res)
def test_sanitizer():
tainted_string = TAINTED_STRING
urlsplit_res = urlsplit(tainted_string)
test(urlsplit_res.netloc) # should be tainted
if urlsplit_res.netloc == "OK":
test(urlsplit_res.netloc)
if urlsplit_res[2] == "OK":
test(urlsplit_res[0])
if urlsplit_res.netloc == "OK":
test(urlsplit_res.path) # FN
if urlsplit_res.netloc in ["OK"]:
test(urlsplit_res.netloc)
if urlsplit_res.netloc in ["OK", non_constant()]:
test(urlsplit_res.netloc) # should be tainted
def test_namedtuple():
tainted_string = TAINTED_STRING
Point = namedtuple('Point', ['x', 'y'])
p = Point('safe', tainted_string)
a = p.x
b = p.y
c = p[0]
d = p[1]
test(a, b, c, d) # TODO: FN, at least p.y and p[1] should be tainted

View File

@@ -1,16 +0,0 @@
| Taint exception.info | test.py:41 | test.py:41:22:41:26 | taint | p1 = exception.info |
| Taint exception.info | test.py:42 | test.py:42:12:42:22 | func() | p1 = exception.info |
| Taint exception.info | test.py:42 | test.py:42:17:42:21 | taint | p1 = exception.info |
| Taint exception.info | test.py:45 | test.py:45:12:45:33 | TAINTED_EXCEPTION_INFO | |
| Taint exception.info | test.py:46 | test.py:46:11:46:41 | cross_over() | |
| Taint exception.info | test.py:46 | test.py:46:37:46:40 | info | |
| Taint exception.info | test.py:48 | test.py:48:19:48:21 | arg | p0 = exception.info |
| Taint exception.info | test.py:49 | test.py:49:12:49:14 | arg | p0 = exception.info |
| Taint externally controlled string | test.py:41 | test.py:41:22:41:26 | taint | p1 = externally controlled string |
| Taint externally controlled string | test.py:42 | test.py:42:12:42:22 | func() | p1 = externally controlled string |
| Taint externally controlled string | test.py:42 | test.py:42:17:42:21 | taint | p1 = externally controlled string |
| Taint externally controlled string | test.py:48 | test.py:48:19:48:21 | arg | p0 = externally controlled string |
| Taint externally controlled string | test.py:49 | test.py:49:12:49:14 | arg | p0 = externally controlled string |
| Taint externally controlled string | test.py:52 | test.py:52:11:52:33 | TAINTED_EXTERNAL_STRING | |
| Taint externally controlled string | test.py:53 | test.py:53:11:53:41 | cross_over() | |
| Taint externally controlled string | test.py:53 | test.py:53:38:53:40 | ext | |

View File

@@ -1,37 +0,0 @@
import python
import semmle.python.security.TaintTracking
import semmle.python.security.Exceptions
import semmle.python.security.strings.Untrusted
class ExceptionInfoSource extends TaintSource {
ExceptionInfoSource() { this.(NameNode).getId() = "TAINTED_EXCEPTION_INFO" }
override predicate isSourceOf(TaintKind kind) {
kind instanceof ExceptionInfo
}
override string toString() {
result = "Exception info source"
}
}
class ExternalStringSource extends TaintSource {
ExternalStringSource() { this.(NameNode).getId() = "TAINTED_EXTERNAL_STRING" }
override predicate isSourceOf(TaintKind kind) {
kind instanceof ExternalStringKind
}
override string toString() {
result = "Untrusted string source"
}
}
from TaintedNode n
where n.getLocation().getFile().getShortName() = "test.py"
select "Taint " + n.getTaintKind(), n.getLocation().toString(), n.getAstNode(), n.getContext()

View File

@@ -1,11 +1,12 @@
import python
import semmle.python.security.TaintTracking
import semmle.python.security.strings.Untrusted
import semmle.python.security.Exceptions
class SimpleSource extends TaintSource {
SimpleSource() { this.(NameNode).getId() = "TAINTED" }
SimpleSource() { this.(NameNode).getId() = "TAINTED_STRING" }
override predicate isSourceOf(TaintKind kind) {
kind instanceof ExternalStringKind
@@ -46,3 +47,16 @@ class DictSource extends TaintSource {
}
class ExceptionInfoSource extends TaintSource {
ExceptionInfoSource() { this.(NameNode).getId() = "TAINTED_EXCEPTION_INFO" }
override predicate isSourceOf(TaintKind kind) {
kind instanceof ExceptionInfo
}
override string toString() {
result = "Exception info source"
}
}

View File

@@ -1,43 +0,0 @@
| Taint externally controlled string | test.py:5 | test.py:5:22:5:28 | TAINTED | |
| Taint externally controlled string | test.py:6 | test.py:6:31:6:44 | tainted_string | |
| Taint externally controlled string | test.py:7 | test.py:7:9:7:25 | Subscript | |
| Taint externally controlled string | test.py:8 | test.py:8:9:8:9 | a | |
| Taint externally controlled string | test.py:8 | test.py:8:9:8:18 | Attribute() | |
| Taint externally controlled string | test.py:9 | test.py:9:9:9:9 | b | |
| Taint externally controlled string | test.py:9 | test.py:9:9:9:14 | Subscript | |
| Taint externally controlled string | test.py:12 | test.py:12:22:12:28 | TAINTED | |
| Taint externally controlled string | test.py:13 | test.py:13:9:13:22 | tainted_string | |
| Taint externally controlled string | test.py:13 | test.py:13:9:13:31 | Attribute() | |
| Taint externally controlled string | test.py:14 | test.py:14:9:14:22 | tainted_string | |
| Taint externally controlled string | test.py:14 | test.py:14:9:14:29 | Attribute() | |
| Taint externally controlled string | test.py:15 | test.py:15:9:15:22 | tainted_string | |
| Taint externally controlled string | test.py:15 | test.py:15:9:15:25 | Subscript | |
| Taint externally controlled string | test.py:16 | test.py:16:9:16:22 | tainted_string | |
| Taint externally controlled string | test.py:16 | test.py:16:9:16:27 | Subscript | |
| Taint externally controlled string | test.py:17 | test.py:17:9:17:32 | reversed() | |
| Taint externally controlled string | test.py:17 | test.py:17:18:17:31 | tainted_string | |
| Taint externally controlled string | test.py:18 | test.py:18:9:18:28 | copy() | |
| Taint externally controlled string | test.py:18 | test.py:18:14:18:27 | tainted_string | |
| Taint externally controlled string | test.py:19 | test.py:19:9:19:22 | tainted_string | |
| Taint externally controlled string | test.py:19 | test.py:19:9:19:30 | Attribute() | |
| Taint externally controlled string | test.py:22 | test.py:22:22:22:28 | TAINTED | |
| Taint externally controlled string | test.py:23 | test.py:23:8:23:21 | tainted_string | |
| Taint externally controlled string | test.py:26 | test.py:26:23:26:36 | tainted_string | |
| Taint externally controlled string | test.py:29 | test.py:29:22:29:28 | TAINTED | |
| Taint externally controlled string | test.py:30 | test.py:30:8:30:21 | tainted_string | |
| Taint externally controlled string | test.py:30 | test.py:30:34:30:47 | tainted_string | |
| Taint externally controlled string | test.py:33 | test.py:33:23:33:36 | tainted_string | |
| Taint externally controlled string | test.py:36 | test.py:36:22:36:28 | TAINTED | |
| Taint externally controlled string | test.py:37 | test.py:37:9:37:27 | str() | |
| Taint externally controlled string | test.py:37 | test.py:37:13:37:26 | tainted_string | |
| Taint externally controlled string | test.py:38 | test.py:38:9:38:29 | bytes() | |
| Taint externally controlled string | test.py:38 | test.py:38:15:38:28 | tainted_string | |
| Taint externally controlled string | test.py:39 | test.py:39:9:39:46 | bytes() | |
| Taint externally controlled string | test.py:39 | test.py:39:15:39:28 | tainted_string | |
| Taint json[externally controlled string] | test.py:6 | test.py:6:20:6:45 | Attribute() | |
| Taint json[externally controlled string] | test.py:7 | test.py:7:9:7:20 | tainted_json | |
| Taint json[externally controlled string] | test.py:7 | test.py:7:9:7:25 | Subscript | |
| Taint json[externally controlled string] | test.py:8 | test.py:8:9:8:9 | a | |
| Taint json[externally controlled string] | test.py:8 | test.py:8:9:8:18 | Attribute() | |
| Taint json[externally controlled string] | test.py:9 | test.py:9:9:9:9 | b | |
| Taint json[externally controlled string] | test.py:9 | test.py:9:9:9:14 | Subscript | |

View File

@@ -1,8 +0,0 @@
import python
import semmle.python.security.TaintTracking
import Taint
from TaintedNode n
where n.getLocation().getFile().getShortName() = "test.py"
select "Taint " + n.getTaintKind(), n.getLocation().toString(), n.getCfgNode().getNode(), n.getContext()

View File

@@ -1,38 +1,76 @@
| Taint externally controlled string | test.py:5 | test.py:5:22:5:28 | TAINTED | | --> | Taint externally controlled string | test.py:6 | test.py:6:31:6:44 | tainted_string | |
| Taint [externally controlled string] | test.py:67 | test.py:67:20:67:43 | urlsplit() | | --> | Taint [externally controlled string] | test.py:69 | test.py:69:10:69:21 | urlsplit_res | |
| Taint [externally controlled string] | test.py:68 | test.py:68:20:68:43 | urlparse() | | --> | Taint [externally controlled string] | test.py:69 | test.py:69:24:69:35 | urlparse_res | |
| Taint exception.info | test.py:44 | test.py:44:22:44:26 | taint | p1 = exception.info | --> | Taint exception.info | test.py:45 | test.py:45:17:45:21 | taint | p1 = exception.info |
| Taint exception.info | test.py:45 | test.py:45:17:45:21 | taint | p1 = exception.info | --> | Taint exception.info | test.py:45 | test.py:45:12:45:22 | func() | p1 = exception.info |
| Taint exception.info | test.py:45 | test.py:45:17:45:21 | taint | p1 = exception.info | --> | Taint exception.info | test.py:52 | test.py:52:19:52:21 | arg | p0 = exception.info |
| Taint exception.info | test.py:48 | test.py:48:12:48:33 | TAINTED_EXCEPTION_INFO | | --> | Taint exception.info | test.py:49 | test.py:49:37:49:40 | info | |
| Taint exception.info | test.py:49 | test.py:49:11:49:41 | cross_over() | | --> | Taint exception.info | test.py:50 | test.py:50:10:50:12 | res | |
| Taint exception.info | test.py:49 | test.py:49:37:49:40 | info | | --> | Taint exception.info | test.py:44 | test.py:44:22:44:26 | taint | p1 = exception.info |
| Taint exception.info | test.py:49 | test.py:49:37:49:40 | info | | --> | Taint exception.info | test.py:49 | test.py:49:11:49:41 | cross_over() | |
| Taint exception.info | test.py:52 | test.py:52:19:52:21 | arg | p0 = exception.info | --> | Taint exception.info | test.py:53 | test.py:53:12:53:14 | arg | p0 = exception.info |
| Taint externally controlled string | test.py:5 | test.py:5:22:5:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:6 | test.py:6:31:6:44 | tainted_string | |
| Taint externally controlled string | test.py:6 | test.py:6:31:6:44 | tainted_string | | --> | Taint json[externally controlled string] | test.py:6 | test.py:6:20:6:45 | Attribute() | |
| Taint externally controlled string | test.py:7 | test.py:7:9:7:25 | Subscript | | --> | Taint externally controlled string | test.py:8 | test.py:8:9:8:9 | a | |
| Taint externally controlled string | test.py:7 | test.py:7:9:7:25 | Subscript | | --> | Taint externally controlled string | test.py:10 | test.py:10:10:10:10 | a | |
| Taint externally controlled string | test.py:8 | test.py:8:9:8:18 | Attribute() | | --> | Taint externally controlled string | test.py:9 | test.py:9:9:9:9 | b | |
| Taint externally controlled string | test.py:12 | test.py:12:22:12:28 | TAINTED | | --> | Taint externally controlled string | test.py:13 | test.py:13:9:13:22 | tainted_string | |
| Taint externally controlled string | test.py:12 | test.py:12:22:12:28 | TAINTED | | --> | Taint externally controlled string | test.py:14 | test.py:14:9:14:22 | tainted_string | |
| Taint externally controlled string | test.py:12 | test.py:12:22:12:28 | TAINTED | | --> | Taint externally controlled string | test.py:15 | test.py:15:9:15:22 | tainted_string | |
| Taint externally controlled string | test.py:12 | test.py:12:22:12:28 | TAINTED | | --> | Taint externally controlled string | test.py:16 | test.py:16:9:16:22 | tainted_string | |
| Taint externally controlled string | test.py:12 | test.py:12:22:12:28 | TAINTED | | --> | Taint externally controlled string | test.py:17 | test.py:17:18:17:31 | tainted_string | |
| Taint externally controlled string | test.py:12 | test.py:12:22:12:28 | TAINTED | | --> | Taint externally controlled string | test.py:18 | test.py:18:14:18:27 | tainted_string | |
| Taint externally controlled string | test.py:12 | test.py:12:22:12:28 | TAINTED | | --> | Taint externally controlled string | test.py:19 | test.py:19:9:19:22 | tainted_string | |
| Taint externally controlled string | test.py:13 | test.py:13:9:13:22 | tainted_string | | --> | Taint externally controlled string | test.py:13 | test.py:13:9:13:31 | Attribute() | |
| Taint externally controlled string | test.py:14 | test.py:14:9:14:22 | tainted_string | | --> | Taint externally controlled string | test.py:14 | test.py:14:9:14:29 | Attribute() | |
| Taint externally controlled string | test.py:15 | test.py:15:9:15:22 | tainted_string | | --> | Taint externally controlled string | test.py:15 | test.py:15:9:15:25 | Subscript | |
| Taint externally controlled string | test.py:16 | test.py:16:9:16:22 | tainted_string | | --> | Taint externally controlled string | test.py:16 | test.py:16:9:16:27 | Subscript | |
| Taint externally controlled string | test.py:17 | test.py:17:18:17:31 | tainted_string | | --> | Taint externally controlled string | test.py:17 | test.py:17:9:17:32 | reversed() | |
| Taint externally controlled string | test.py:18 | test.py:18:14:18:27 | tainted_string | | --> | Taint externally controlled string | test.py:18 | test.py:18:9:18:28 | copy() | |
| Taint externally controlled string | test.py:19 | test.py:19:9:19:22 | tainted_string | | --> | Taint externally controlled string | test.py:19 | test.py:19:9:19:30 | Attribute() | |
| Taint externally controlled string | test.py:22 | test.py:22:22:22:28 | TAINTED | | --> | Taint externally controlled string | test.py:23 | test.py:23:8:23:21 | tainted_string | |
| Taint externally controlled string | test.py:22 | test.py:22:22:22:28 | TAINTED | | --> | Taint externally controlled string | test.py:26 | test.py:26:23:26:36 | tainted_string | |
| Taint externally controlled string | test.py:29 | test.py:29:22:29:28 | TAINTED | | --> | Taint externally controlled string | test.py:30 | test.py:30:8:30:21 | tainted_string | |
| Taint externally controlled string | test.py:29 | test.py:29:22:29:28 | TAINTED | | --> | Taint externally controlled string | test.py:30 | test.py:30:34:30:47 | tainted_string | |
| Taint externally controlled string | test.py:29 | test.py:29:22:29:28 | TAINTED | | --> | Taint externally controlled string | test.py:33 | test.py:33:23:33:36 | tainted_string | |
| Taint externally controlled string | test.py:36 | test.py:36:22:36:28 | TAINTED | | --> | Taint externally controlled string | test.py:37 | test.py:37:13:37:26 | tainted_string | |
| Taint externally controlled string | test.py:36 | test.py:36:22:36:28 | TAINTED | | --> | Taint externally controlled string | test.py:38 | test.py:38:15:38:28 | tainted_string | |
| Taint externally controlled string | test.py:36 | test.py:36:22:36:28 | TAINTED | | --> | Taint externally controlled string | test.py:39 | test.py:39:15:39:28 | tainted_string | |
| Taint externally controlled string | test.py:37 | test.py:37:13:37:26 | tainted_string | | --> | Taint externally controlled string | test.py:37 | test.py:37:9:37:27 | str() | |
| Taint externally controlled string | test.py:38 | test.py:38:15:38:28 | tainted_string | | --> | Taint externally controlled string | test.py:38 | test.py:38:9:38:29 | bytes() | |
| Taint externally controlled string | test.py:39 | test.py:39:15:39:28 | tainted_string | | --> | Taint externally controlled string | test.py:39 | test.py:39:9:39:46 | bytes() | |
| Taint externally controlled string | test.py:8 | test.py:8:9:8:18 | Attribute() | | --> | Taint externally controlled string | test.py:10 | test.py:10:13:10:13 | b | |
| Taint externally controlled string | test.py:9 | test.py:9:9:9:14 | Subscript | | --> | Taint externally controlled string | test.py:10 | test.py:10:16:10:16 | c | |
| Taint externally controlled string | test.py:13 | test.py:13:22:13:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:14 | test.py:14:9:14:22 | tainted_string | |
| Taint externally controlled string | test.py:13 | test.py:13:22:13:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:15 | test.py:15:9:15:22 | tainted_string | |
| Taint externally controlled string | test.py:13 | test.py:13:22:13:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:16 | test.py:16:9:16:22 | tainted_string | |
| Taint externally controlled string | test.py:13 | test.py:13:22:13:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:17 | test.py:17:9:17:22 | tainted_string | |
| Taint externally controlled string | test.py:13 | test.py:13:22:13:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:18 | test.py:18:18:18:31 | tainted_string | |
| Taint externally controlled string | test.py:13 | test.py:13:22:13:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:19 | test.py:19:14:19:27 | tainted_string | |
| Taint externally controlled string | test.py:13 | test.py:13:22:13:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:20 | test.py:20:9:20:22 | tainted_string | |
| Taint externally controlled string | test.py:14 | test.py:14:9:14:22 | tainted_string | | --> | Taint externally controlled string | test.py:14 | test.py:14:9:14:31 | Attribute() | |
| Taint externally controlled string | test.py:14 | test.py:14:9:14:31 | Attribute() | | --> | Taint externally controlled string | test.py:21 | test.py:21:10:21:10 | a | |
| Taint externally controlled string | test.py:15 | test.py:15:9:15:22 | tainted_string | | --> | Taint externally controlled string | test.py:15 | test.py:15:9:15:29 | Attribute() | |
| Taint externally controlled string | test.py:15 | test.py:15:9:15:29 | Attribute() | | --> | Taint externally controlled string | test.py:21 | test.py:21:13:21:13 | b | |
| Taint externally controlled string | test.py:16 | test.py:16:9:16:22 | tainted_string | | --> | Taint externally controlled string | test.py:16 | test.py:16:9:16:25 | Subscript | |
| Taint externally controlled string | test.py:16 | test.py:16:9:16:25 | Subscript | | --> | Taint externally controlled string | test.py:21 | test.py:21:16:21:16 | c | |
| Taint externally controlled string | test.py:17 | test.py:17:9:17:22 | tainted_string | | --> | Taint externally controlled string | test.py:17 | test.py:17:9:17:27 | Subscript | |
| Taint externally controlled string | test.py:17 | test.py:17:9:17:27 | Subscript | | --> | Taint externally controlled string | test.py:21 | test.py:21:19:21:19 | d | |
| Taint externally controlled string | test.py:18 | test.py:18:9:18:32 | reversed() | | --> | Taint externally controlled string | test.py:21 | test.py:21:22:21:22 | e | |
| Taint externally controlled string | test.py:18 | test.py:18:18:18:31 | tainted_string | | --> | Taint externally controlled string | test.py:18 | test.py:18:9:18:32 | reversed() | |
| Taint externally controlled string | test.py:19 | test.py:19:9:19:28 | copy() | | --> | Taint externally controlled string | test.py:21 | test.py:21:25:21:25 | f | |
| Taint externally controlled string | test.py:19 | test.py:19:14:19:27 | tainted_string | | --> | Taint externally controlled string | test.py:19 | test.py:19:9:19:28 | copy() | |
| Taint externally controlled string | test.py:20 | test.py:20:9:20:22 | tainted_string | | --> | Taint externally controlled string | test.py:20 | test.py:20:9:20:30 | Attribute() | |
| Taint externally controlled string | test.py:20 | test.py:20:9:20:30 | Attribute() | | --> | Taint externally controlled string | test.py:21 | test.py:21:28:21:28 | g | |
| Taint externally controlled string | test.py:24 | test.py:24:22:24:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:25 | test.py:25:8:25:21 | tainted_string | |
| Taint externally controlled string | test.py:24 | test.py:24:22:24:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:28 | test.py:28:14:28:27 | tainted_string | |
| Taint externally controlled string | test.py:31 | test.py:31:22:31:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:32 | test.py:32:8:32:21 | tainted_string | |
| Taint externally controlled string | test.py:31 | test.py:31:22:31:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:32 | test.py:32:34:32:47 | tainted_string | |
| Taint externally controlled string | test.py:31 | test.py:31:22:31:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:35 | test.py:35:14:35:27 | tainted_string | |
| Taint externally controlled string | test.py:38 | test.py:38:22:38:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:39 | test.py:39:13:39:26 | tainted_string | |
| Taint externally controlled string | test.py:38 | test.py:38:22:38:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:40 | test.py:40:15:40:28 | tainted_string | |
| Taint externally controlled string | test.py:38 | test.py:38:22:38:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:41 | test.py:41:15:41:28 | tainted_string | |
| Taint externally controlled string | test.py:39 | test.py:39:9:39:27 | str() | | --> | Taint externally controlled string | test.py:42 | test.py:42:10:42:10 | a | |
| Taint externally controlled string | test.py:39 | test.py:39:13:39:26 | tainted_string | | --> | Taint externally controlled string | test.py:39 | test.py:39:9:39:27 | str() | |
| Taint externally controlled string | test.py:40 | test.py:40:9:40:29 | bytes() | | --> | Taint externally controlled string | test.py:42 | test.py:42:13:42:13 | b | |
| Taint externally controlled string | test.py:40 | test.py:40:15:40:28 | tainted_string | | --> | Taint externally controlled string | test.py:40 | test.py:40:9:40:29 | bytes() | |
| Taint externally controlled string | test.py:41 | test.py:41:9:41:46 | bytes() | | --> | Taint externally controlled string | test.py:42 | test.py:42:16:42:16 | c | |
| Taint externally controlled string | test.py:41 | test.py:41:15:41:28 | tainted_string | | --> | Taint externally controlled string | test.py:41 | test.py:41:9:41:46 | bytes() | |
| Taint externally controlled string | test.py:44 | test.py:44:22:44:26 | taint | p1 = externally controlled string | --> | Taint externally controlled string | test.py:45 | test.py:45:17:45:21 | taint | p1 = externally controlled string |
| Taint externally controlled string | test.py:45 | test.py:45:17:45:21 | taint | p1 = externally controlled string | --> | Taint externally controlled string | test.py:45 | test.py:45:12:45:22 | func() | p1 = externally controlled string |
| Taint externally controlled string | test.py:45 | test.py:45:17:45:21 | taint | p1 = externally controlled string | --> | Taint externally controlled string | test.py:52 | test.py:52:19:52:21 | arg | p0 = externally controlled string |
| Taint externally controlled string | test.py:52 | test.py:52:19:52:21 | arg | p0 = externally controlled string | --> | Taint externally controlled string | test.py:53 | test.py:53:12:53:14 | arg | p0 = externally controlled string |
| Taint externally controlled string | test.py:56 | test.py:56:11:56:24 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:57 | test.py:57:38:57:40 | ext | |
| Taint externally controlled string | test.py:57 | test.py:57:11:57:41 | cross_over() | | --> | Taint externally controlled string | test.py:58 | test.py:58:10:58:12 | res | |
| Taint externally controlled string | test.py:57 | test.py:57:38:57:40 | ext | | --> | Taint externally controlled string | test.py:44 | test.py:44:22:44:26 | taint | p1 = externally controlled string |
| Taint externally controlled string | test.py:57 | test.py:57:38:57:40 | ext | | --> | Taint externally controlled string | test.py:57 | test.py:57:11:57:41 | cross_over() | |
| Taint externally controlled string | test.py:66 | test.py:66:22:66:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:67 | test.py:67:29:67:42 | tainted_string | |
| Taint externally controlled string | test.py:66 | test.py:66:22:66:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:68 | test.py:68:29:68:42 | tainted_string | |
| Taint externally controlled string | test.py:67 | test.py:67:29:67:42 | tainted_string | | --> | Taint [externally controlled string] | test.py:67 | test.py:67:20:67:43 | urlsplit() | |
| Taint externally controlled string | test.py:68 | test.py:68:29:68:42 | tainted_string | | --> | Taint [externally controlled string] | test.py:68 | test.py:68:20:68:43 | urlparse() | |
| Taint json[externally controlled string] | test.py:6 | test.py:6:20:6:45 | Attribute() | | --> | Taint json[externally controlled string] | test.py:7 | test.py:7:9:7:20 | tainted_json | |
| Taint json[externally controlled string] | test.py:7 | test.py:7:9:7:20 | tainted_json | | --> | Taint externally controlled string | test.py:7 | test.py:7:9:7:25 | Subscript | |
| Taint json[externally controlled string] | test.py:7 | test.py:7:9:7:20 | tainted_json | | --> | Taint json[externally controlled string] | test.py:7 | test.py:7:9:7:25 | Subscript | |
| Taint json[externally controlled string] | test.py:7 | test.py:7:9:7:25 | Subscript | | --> | Taint json[externally controlled string] | test.py:8 | test.py:8:9:8:9 | a | |
| Taint json[externally controlled string] | test.py:7 | test.py:7:9:7:25 | Subscript | | --> | Taint json[externally controlled string] | test.py:10 | test.py:10:10:10:10 | a | |
| Taint json[externally controlled string] | test.py:8 | test.py:8:9:8:9 | a | | --> | Taint externally controlled string | test.py:8 | test.py:8:9:8:18 | Attribute() | |
| Taint json[externally controlled string] | test.py:8 | test.py:8:9:8:9 | a | | --> | Taint json[externally controlled string] | test.py:8 | test.py:8:9:8:18 | Attribute() | |
| Taint json[externally controlled string] | test.py:8 | test.py:8:9:8:18 | Attribute() | | --> | Taint json[externally controlled string] | test.py:9 | test.py:9:9:9:9 | b | |
| Taint json[externally controlled string] | test.py:8 | test.py:8:9:8:18 | Attribute() | | --> | Taint json[externally controlled string] | test.py:10 | test.py:10:13:10:13 | b | |
| Taint json[externally controlled string] | test.py:9 | test.py:9:9:9:9 | b | | --> | Taint externally controlled string | test.py:9 | test.py:9:9:9:14 | Subscript | |
| Taint json[externally controlled string] | test.py:9 | test.py:9:9:9:9 | b | | --> | Taint json[externally controlled string] | test.py:9 | test.py:9:9:9:14 | Subscript | |
| Taint json[externally controlled string] | test.py:9 | test.py:9:9:9:14 | Subscript | | --> | Taint json[externally controlled string] | test.py:10 | test.py:10:16:10:16 | c | |

View File

@@ -0,0 +1,24 @@
| test.py:10 | test_json | a | externally controlled string |
| test.py:10 | test_json | a | json[externally controlled string] |
| test.py:10 | test_json | b | externally controlled string |
| test.py:10 | test_json | b | json[externally controlled string] |
| test.py:10 | test_json | c | externally controlled string |
| test.py:10 | test_json | c | json[externally controlled string] |
| test.py:21 | test_str | a | externally controlled string |
| test.py:21 | test_str | b | externally controlled string |
| test.py:21 | test_str | c | externally controlled string |
| test.py:21 | test_str | d | externally controlled string |
| test.py:21 | test_str | e | externally controlled string |
| test.py:21 | test_str | f | externally controlled string |
| test.py:21 | test_str | g | externally controlled string |
| test.py:26 | test_const_sanitizer1 | tainted_string | NO TAINT |
| test.py:28 | test_const_sanitizer1 | tainted_string | externally controlled string |
| test.py:33 | test_const_sanitizer2 | tainted_string | NO TAINT |
| test.py:35 | test_const_sanitizer2 | tainted_string | externally controlled string |
| test.py:42 | test_str2 | a | externally controlled string |
| test.py:42 | test_str2 | b | externally controlled string |
| test.py:42 | test_str2 | c | externally controlled string |
| test.py:50 | test_exc_info | res | exception.info |
| test.py:58 | test_untrusted | res | externally controlled string |
| test.py:69 | test_urlsplit_urlparse | urlparse_res | [externally controlled string] |
| test.py:69 | test_urlsplit_urlparse | urlsplit_res | [externally controlled string] |

View File

@@ -0,0 +1,18 @@
import python
import semmle.python.security.TaintTracking
import Taint
from Call call, Expr arg, string taint_string
where
call.getLocation().getFile().getShortName() = "test.py" and
call.getFunc().(Name).getId() = "test" and
arg = call.getAnArg() and
(
not exists(TaintedNode tainted | tainted.getAstNode() = arg) and
taint_string = "NO TAINT"
or
exists(TaintedNode tainted | tainted.getAstNode() = arg |
taint_string = tainted.getTaintKind().toString()
)
)
select arg.getLocation().toString(), call.getScope().(Function).getName(), arg.toString(), taint_string

View File

@@ -2,41 +2,44 @@ import json
from copy import copy
def test_json():
tainted_string = TAINTED
tainted_string = TAINTED_STRING
tainted_json = json.loads(tainted_string)
a = tainted_json["x"]
b = a.get("y")
c = b["z"]
test(a, b, c)
def test_str():
tainted_string = TAINTED
tainted_string = TAINTED_STRING
a = tainted_string.ljust(8)
b = tainted_string.copy()
c = tainted_string[:]
d = tainted_string[::2]
e = reversed(tainted_string)
f = copy(tainted_string)
h = tainted_string.strip()
g = tainted_string.strip()
test(a, b, c, d, e, f, g)
def test_const_sanitizer1():
tainted_string = TAINTED
tainted_string = TAINTED_STRING
if tainted_string == "OK":
not_tainted(tainted_string)
test(tainted_string) # not tainted
else:
still_tainted(tainted_string)
test(tainted_string) # still tainted
def test_const_sanitizer2():
tainted_string = TAINTED
tainted_string = TAINTED_STRING
if tainted_string == "OK" or tainted_string == "ALSO_OK":
not_tainted(tainted_string)
test(tainted_string) # not tainted
else:
still_tainted(tainted_string)
test(tainted_string) # still tainted
def test_str2():
tainted_string = TAINTED
tainted_string = TAINTED_STRING
a = str(tainted_string)
b = bytes(tainted_string) # This is an error in Python 3
c = bytes(tainted_string, encoding="utf8") # This is an error in Python 2
test(a, b, c)
def cross_over(func, taint):
return func(taint)
@@ -44,13 +47,23 @@ def cross_over(func, taint):
def test_exc_info():
info = TAINTED_EXCEPTION_INFO
res = cross_over(exc_info_call, info)
test(res)
def exc_info_call(arg):
return arg
def test_untrusted():
ext = TAINTED_EXTERNAL_STRING
ext = TAINTED_STRING
res = cross_over(untrusted_call, ext)
test(res)
def exc_untrusted_call(arg):
return arg
from six.moves.urllib.parse import urlsplit, urlparse
def test_urlsplit_urlparse():
tainted_string = TAINTED_STRING
urlsplit_res = urlsplit(tainted_string)
urlparse_res = urlparse(tainted_string)
test(urlsplit_res, urlparse_res)

View File

@@ -1,35 +1,8 @@
| 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 | 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: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: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 | 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: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:56 | contrived_2 | a | NO TAINT |
| test.py:56 | contrived_2 | b | NO TAINT |
| test.py:56 | contrived_2 | c | NO TAINT |

View File

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

View File

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

View File

@@ -0,0 +1,2 @@
| test.py:3:1:3:27 | ControlFlowNode for Attribute() | test.py:3:14:3:26 | ControlFlowNode for Str | GET |
| test.py:4:1:4:28 | ControlFlowNode for Attribute() | test.py:4:15:4:27 | ControlFlowNode for Str | POST |

View File

@@ -0,0 +1,11 @@
import python
import semmle.python.web.Http
import semmle.python.web.ClientHttpRequest
from Client::HttpRequest req, string method
where
if exists(req.getMethodUpper())
then method = req.getMethodUpper()
else method = "<NO METHOD>"
select req, req.getAUrlPart(), method

View File

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

View File

@@ -0,0 +1,4 @@
import requests
requests.get('example.com')
requests.post('example.com')

View File

@@ -0,0 +1,10 @@
| test.py:6:5:6:32 | ControlFlowNode for Attribute() | test.py:5:27:5:39 | ControlFlowNode for Str | GET |
| test.py:6:5:6:32 | ControlFlowNode for Attribute() | test.py:6:25:6:31 | ControlFlowNode for Str | GET |
| test.py:15:5:15:33 | ControlFlowNode for Attribute() | test.py:10:28:10:40 | ControlFlowNode for Str | POST |
| test.py:15:5:15:33 | ControlFlowNode for Attribute() | test.py:15:26:15:32 | ControlFlowNode for Str | POST |
| test.py:20:5:20:33 | ControlFlowNode for Attribute() | test.py:19:27:19:39 | ControlFlowNode for Str | <NO METHOD> |
| test.py:20:5:20:33 | ControlFlowNode for Attribute() | test.py:20:26:20:32 | ControlFlowNode for Str | <NO METHOD> |
| test.py:30:5:30:32 | ControlFlowNode for Attribute() | test.py:28:27:28:30 | ControlFlowNode for fake | GET |
| test.py:30:5:30:32 | ControlFlowNode for Attribute() | test.py:30:25:30:31 | ControlFlowNode for Str | GET |
| test.py:37:5:37:29 | ControlFlowNode for req_meth() | test.py:35:27:35:39 | ControlFlowNode for Str | HEAD |
| test.py:37:5:37:29 | ControlFlowNode for req_meth() | test.py:37:22:37:28 | ControlFlowNode for Str | HEAD |

View File

@@ -0,0 +1,11 @@
import python
import semmle.python.web.Http
import semmle.python.web.ClientHttpRequest
from Client::HttpRequest req, string method
where
if exists(req.getMethodUpper())
then method = req.getMethodUpper()
else method = "<NO METHOD>"
select req, req.getAUrlPart(), method

View File

@@ -0,0 +1,2 @@
semmle-extractor-options: --max-import-depth=2
optimize: true

View File

@@ -0,0 +1,37 @@
from six.moves.http_client import HTTPConnection, HTTPSConnection
def basic():
conn = HTTPConnection('example.com')
conn.request('GET', '/path')
def indirect_caller():
conn = HTTPSConnection('example.com')
indirect_callee(conn)
def indirect_callee(conn):
conn.request('POST', '/path')
def method_not_known(method):
conn = HTTPConnection('example.com')
conn.request(method, '/path')
def sneaky_setting_host():
# We don't handle that the host is overwritten directly.
# A contrived example; you're not supposed to do this, but you certainly can.
fake = 'fakehost.com'
real = 'realhost.com'
conn = HTTPConnection(fake)
conn.host = real
conn.request('GET', '/path')
def tricky_not_attribute_node():
# A contrived example; you're not supposed to do this, but you certainly can.
conn = HTTPConnection('example.com')
req_meth = conn.request
req_meth('HEAD', '/path')

View File

@@ -0,0 +1,10 @@
| test.py:13:5:13:32 | ControlFlowNode for Attribute() | test.py:12:27:12:39 | ControlFlowNode for Str | GET |
| test.py:13:5:13:32 | ControlFlowNode for Attribute() | test.py:13:25:13:31 | ControlFlowNode for Str | GET |
| test.py:22:5:22:33 | ControlFlowNode for Attribute() | test.py:17:28:17:40 | ControlFlowNode for Str | POST |
| test.py:22:5:22:33 | ControlFlowNode for Attribute() | test.py:22:26:22:32 | ControlFlowNode for Str | POST |
| test.py:27:5:27:33 | ControlFlowNode for Attribute() | test.py:26:27:26:39 | ControlFlowNode for Str | <NO METHOD> |
| test.py:27:5:27:33 | ControlFlowNode for Attribute() | test.py:27:26:27:32 | ControlFlowNode for Str | <NO METHOD> |
| test.py:37:5:37:32 | ControlFlowNode for Attribute() | test.py:35:27:35:30 | ControlFlowNode for fake | GET |
| test.py:37:5:37:32 | ControlFlowNode for Attribute() | test.py:37:25:37:31 | ControlFlowNode for Str | GET |
| test.py:44:5:44:29 | ControlFlowNode for req_meth() | test.py:42:27:42:39 | ControlFlowNode for Str | HEAD |
| test.py:44:5:44:29 | ControlFlowNode for req_meth() | test.py:44:22:44:28 | ControlFlowNode for Str | HEAD |

View File

@@ -0,0 +1,11 @@
import python
import semmle.python.web.Http
import semmle.python.web.ClientHttpRequest
from Client::HttpRequest req, string method
where
if exists(req.getMethodUpper())
then method = req.getMethodUpper()
else method = "<NO METHOD>"
select req, req.getAUrlPart(), method

View File

@@ -0,0 +1 @@
semmle-extractor-options: --max-import-depth=1

View File

@@ -0,0 +1,44 @@
import sys
PY2 = sys.version_info[0] == 2
PY3 = sys.version_info[0] == 3
if PY2:
from httplib import HTTPConnection, HTTPSConnection
if PY3:
from http.client import HTTPConnection, HTTPSConnection
def basic():
conn = HTTPConnection('example.com')
conn.request('GET', '/path')
def indirect_caller():
conn = HTTPSConnection('example.com')
indirect_callee(conn)
def indirect_callee(conn):
conn.request('POST', '/path')
def method_not_known(method):
conn = HTTPConnection('example.com')
conn.request(method, '/path')
def sneaky_setting_host():
# We don't handle that the host is overwritten directly.
# A contrived example; you're not supposed to do this, but you certainly can.
fake = 'fakehost.com'
real = 'realhost.com'
conn = HTTPConnection(fake)
conn.host = real
conn.request('GET', '/path')
def tricky_not_attribute_node():
# A contrived example; you're not supposed to do this, but you certainly can.
conn = HTTPConnection('example.com')
req_meth = conn.request
req_meth('HEAD', '/path')

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1 +1 @@
| str_fmt_test.py:5:26:5:26 | x | Right hand side of a % operator must be a mapping, not class $@. | file://:Compiled Code:0:0:0:0 | builtin-class list | list |
| str_fmt_test.py:5:26:5:26 | x | Right hand side of a % operator must be a mapping, not class $@. | file://:0:0:0:0 | builtin-class list | list |

View File

@@ -242,3 +242,40 @@ from types import MappingProxyType
def mpt_arg(d=MappingProxyType({})):
return 1 in d
#### UseofApply.ql
# Use of the builtin function `apply` is generally considered bad now that the
# ability to destructure lists of arguments is possible, but we should not flag
# cases where the function is merely named `apply` rather than being the actual
# builtin `apply` function.
def useofapply():
def foo():
pass
# Positive Cases
# This use of `apply` is a reference to the builtin function and so SHOULD be
# caught by the query.
apply(foo, [1])
# Negative Cases
# This use of `apply` is a reference to the locally defined function inside of
# `local`, and so SHOULD NOT be caught by the query.
def local():
def apply(f):
pass
apply(foo)([1])

View File

@@ -1,3 +1,3 @@
| functions_test.py:99:5:99:40 | Function __getslice__ | __getslice__ method has been deprecated since Python 2.0 |
| functions_test.py:102:5:102:47 | Function __setslice__ | __setslice__ method has been deprecated since Python 2.0 |
| functions_test.py:105:5:105:40 | Function __delslice__ | __delslice__ method has been deprecated since Python 2.0 |
| functions_test.py:99:5:99:40 | Function DeprecatedSliceMethods.__getslice__ | __getslice__ method has been deprecated since Python 2.0 |
| functions_test.py:102:5:102:47 | Function DeprecatedSliceMethods.__setslice__ | __setslice__ method has been deprecated since Python 2.0 |
| functions_test.py:105:5:105:40 | Function DeprecatedSliceMethods.__delslice__ | __delslice__ method has been deprecated since Python 2.0 |

View File

@@ -1,9 +1,9 @@
| om_test.py:59:5:59:28 | Function __div__ | Too many parameters for special method __div__, which has 3 parameters, but should have 2, in class $@. | om_test.py:57:1:57:28 | class WrongSpecials | WrongSpecials |
| om_test.py:62:5:62:22 | Function __mul__ | Too few parameters for special method __mul__, which has 1 parameter, but should have 2, in class $@. | om_test.py:57:1:57:28 | class WrongSpecials | WrongSpecials |
| om_test.py:65:5:65:29 | Function __neg__ | Too many parameters for special method __neg__, which has 2 parameters, but should have 1, in class $@. | om_test.py:57:1:57:28 | class WrongSpecials | WrongSpecials |
| om_test.py:68:5:68:35 | Function __exit__ | Too few parameters for special method __exit__, which has 3 parameters, but should have 4, in class $@. | om_test.py:57:1:57:28 | class WrongSpecials | WrongSpecials |
| om_test.py:71:5:71:19 | Function __repr__ | Too few parameters for special method __repr__, which has no parameters, but should have 1, in class $@. | om_test.py:57:1:57:28 | class WrongSpecials | WrongSpecials |
| om_test.py:74:5:74:46 | Function __add__ | 1 default values(s) will never be used for special method __add__, in class $@. | om_test.py:57:1:57:28 | class WrongSpecials | WrongSpecials |
| om_test.py:97:15:97:34 | Function lambda | Too few parameters for special method __sub__, which has 1 parameter, but should have 2, in class $@. | om_test.py:95:1:95:28 | class NotOKSpecials | NotOKSpecials |
| om_test.py:59:5:59:28 | Function WrongSpecials.__div__ | Too many parameters for special method __div__, which has 3 parameters, but should have 2, in class $@. | om_test.py:57:1:57:28 | class WrongSpecials | WrongSpecials |
| om_test.py:62:5:62:22 | Function WrongSpecials.__mul__ | Too few parameters for special method __mul__, which has 1 parameter, but should have 2, in class $@. | om_test.py:57:1:57:28 | class WrongSpecials | WrongSpecials |
| om_test.py:65:5:65:29 | Function WrongSpecials.__neg__ | Too many parameters for special method __neg__, which has 2 parameters, but should have 1, in class $@. | om_test.py:57:1:57:28 | class WrongSpecials | WrongSpecials |
| om_test.py:68:5:68:35 | Function WrongSpecials.__exit__ | Too few parameters for special method __exit__, which has 3 parameters, but should have 4, in class $@. | om_test.py:57:1:57:28 | class WrongSpecials | WrongSpecials |
| om_test.py:71:5:71:19 | Function WrongSpecials.__repr__ | Too few parameters for special method __repr__, which has no parameters, but should have 1, in class $@. | om_test.py:57:1:57:28 | class WrongSpecials | WrongSpecials |
| om_test.py:74:5:74:46 | Function WrongSpecials.__add__ | 1 default values(s) will never be used for special method __add__, in class $@. | om_test.py:57:1:57:28 | class WrongSpecials | WrongSpecials |
| om_test.py:97:15:97:34 | Function NotOKSpecials.lambda | Too few parameters for special method __sub__, which has 1 parameter, but should have 2, in class $@. | om_test.py:95:1:95:28 | class NotOKSpecials | NotOKSpecials |
| protocols.py:104:1:104:12 | Function f | Too few parameters for special method __add__, which has 1 parameter, but should have 2, in class $@. | protocols.py:107:1:107:29 | class MissingMethods | MissingMethods |
| protocols.py:104:1:104:12 | Function f | Too few parameters for special method __set__, which has 1 parameter, but should have 3, in class $@. | protocols.py:107:1:107:29 | class MissingMethods | MissingMethods |

View File

@@ -1,2 +1 @@
semmle-extractor-options: -p ../lib/ --max-import-depth=3
optimize: true

View File

@@ -1,2 +1 @@
semmle-extractor-options: -p ../lib/ --max-import-depth=3
optimize: true

View File

@@ -1,2 +1 @@
semmle-extractor-options: -p ../lib/ --max-import-depth=3
optimize: true

Some files were not shown because too many files have changed in this diff Show More