diff --git a/python/ql/test/2/query-tests/Classes/inconsistent-mro/InconsistentMRO.qlref b/python/ql/test/2/query-tests/Classes/inconsistent-mro/InconsistentMRO.qlref
index f43176f3d7a..e2e9a180ab1 100644
--- a/python/ql/test/2/query-tests/Classes/inconsistent-mro/InconsistentMRO.qlref
+++ b/python/ql/test/2/query-tests/Classes/inconsistent-mro/InconsistentMRO.qlref
@@ -1 +1,2 @@
-Classes/InconsistentMRO.ql
\ No newline at end of file
+query: Classes/InconsistentMRO.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/2/query-tests/Classes/inconsistent-mro/inconsistent_mro.py b/python/ql/test/2/query-tests/Classes/inconsistent-mro/inconsistent_mro.py
index 34677864834..a8e76c6bfb1 100644
--- a/python/ql/test/2/query-tests/Classes/inconsistent-mro/inconsistent_mro.py
+++ b/python/ql/test/2/query-tests/Classes/inconsistent-mro/inconsistent_mro.py
@@ -6,7 +6,7 @@ class X(object):
class Y(X):
pass
-class Z(X, Y):
+class Z(X, Y): # $ Alert
pass
class O:
diff --git a/python/ql/test/2/query-tests/Classes/new-style/PropertyInOldStyleClass.qlref b/python/ql/test/2/query-tests/Classes/new-style/PropertyInOldStyleClass.qlref
index 297295c006e..fa194766511 100644
--- a/python/ql/test/2/query-tests/Classes/new-style/PropertyInOldStyleClass.qlref
+++ b/python/ql/test/2/query-tests/Classes/new-style/PropertyInOldStyleClass.qlref
@@ -1 +1,2 @@
-Classes/PropertyInOldStyleClass.ql
+query: Classes/PropertyInOldStyleClass.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/2/query-tests/Classes/new-style/SlotsInOldStyleClass.qlref b/python/ql/test/2/query-tests/Classes/new-style/SlotsInOldStyleClass.qlref
index 62fb3202a16..688f31402ad 100644
--- a/python/ql/test/2/query-tests/Classes/new-style/SlotsInOldStyleClass.qlref
+++ b/python/ql/test/2/query-tests/Classes/new-style/SlotsInOldStyleClass.qlref
@@ -1 +1,2 @@
-Classes/SlotsInOldStyleClass.ql
\ No newline at end of file
+query: Classes/SlotsInOldStyleClass.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/2/query-tests/Classes/new-style/SuperInOldStyleClass.qlref b/python/ql/test/2/query-tests/Classes/new-style/SuperInOldStyleClass.qlref
index 08f737893ef..293fc72d86c 100644
--- a/python/ql/test/2/query-tests/Classes/new-style/SuperInOldStyleClass.qlref
+++ b/python/ql/test/2/query-tests/Classes/new-style/SuperInOldStyleClass.qlref
@@ -1 +1,2 @@
-Classes/SuperInOldStyleClass.ql
\ No newline at end of file
+query: Classes/SuperInOldStyleClass.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/2/query-tests/Classes/new-style/newstyle_test.py b/python/ql/test/2/query-tests/Classes/new-style/newstyle_test.py
index f1e3ea8e42c..44dce333ef9 100644
--- a/python/ql/test/2/query-tests/Classes/new-style/newstyle_test.py
+++ b/python/ql/test/2/query-tests/Classes/new-style/newstyle_test.py
@@ -1,7 +1,7 @@
#Only works for Python2
-class OldStyle1:
+class OldStyle1: # $ Alert[py/slots-in-old-style-class]
__slots__ = [ 'a', 'b' ]
@@ -12,7 +12,7 @@ class OldStyle1:
class OldStyle2:
def __init__(self, x):
- super().__init__(x)
+ super().__init__(x) # $ Alert[py/super-in-old-style]
class NewStyle1(object):
diff --git a/python/ql/test/2/query-tests/Classes/new-style/property_old_style.py b/python/ql/test/2/query-tests/Classes/new-style/property_old_style.py
index 8291feab26c..0b529d9edb7 100644
--- a/python/ql/test/2/query-tests/Classes/new-style/property_old_style.py
+++ b/python/ql/test/2/query-tests/Classes/new-style/property_old_style.py
@@ -5,6 +5,6 @@ class OldStyle:
def __init__(self, x):
self._x = x
- @property
+ @property # $ Alert[py/property-in-old-style-class]
def piosc(self):
return self._x
\ No newline at end of file
diff --git a/python/ql/test/2/query-tests/Classes/undefined-attribute/MaybeUndefinedClassAttribute.qlref b/python/ql/test/2/query-tests/Classes/undefined-attribute/MaybeUndefinedClassAttribute.qlref
index d4986ffc84c..35f6da7add5 100644
--- a/python/ql/test/2/query-tests/Classes/undefined-attribute/MaybeUndefinedClassAttribute.qlref
+++ b/python/ql/test/2/query-tests/Classes/undefined-attribute/MaybeUndefinedClassAttribute.qlref
@@ -1 +1,2 @@
-Classes/MaybeUndefinedClassAttribute.ql
+query: Classes/MaybeUndefinedClassAttribute.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/2/query-tests/Classes/undefined-attribute/UndefinedClassAttribute.qlref b/python/ql/test/2/query-tests/Classes/undefined-attribute/UndefinedClassAttribute.qlref
index 7ac0a3b18b7..f0e8fb72278 100644
--- a/python/ql/test/2/query-tests/Classes/undefined-attribute/UndefinedClassAttribute.qlref
+++ b/python/ql/test/2/query-tests/Classes/undefined-attribute/UndefinedClassAttribute.qlref
@@ -1 +1,2 @@
-Classes/UndefinedClassAttribute.ql
+query: Classes/UndefinedClassAttribute.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/2/query-tests/Exceptions/general/CatchingBaseException.qlref b/python/ql/test/2/query-tests/Exceptions/general/CatchingBaseException.qlref
index 5588dbf2c7b..33b4697e7ef 100644
--- a/python/ql/test/2/query-tests/Exceptions/general/CatchingBaseException.qlref
+++ b/python/ql/test/2/query-tests/Exceptions/general/CatchingBaseException.qlref
@@ -1 +1,2 @@
-Exceptions/CatchingBaseException.ql
\ No newline at end of file
+query: Exceptions/CatchingBaseException.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/2/query-tests/Exceptions/general/EmptyExcept.qlref b/python/ql/test/2/query-tests/Exceptions/general/EmptyExcept.qlref
index 3f4987046b1..7a046d008cd 100644
--- a/python/ql/test/2/query-tests/Exceptions/general/EmptyExcept.qlref
+++ b/python/ql/test/2/query-tests/Exceptions/general/EmptyExcept.qlref
@@ -1 +1,2 @@
-Exceptions/EmptyExcept.ql
\ No newline at end of file
+query: Exceptions/EmptyExcept.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/2/query-tests/Exceptions/general/IllegalExceptionHandlerType.qlref b/python/ql/test/2/query-tests/Exceptions/general/IllegalExceptionHandlerType.qlref
index 6d49710a759..7a7911ca440 100644
--- a/python/ql/test/2/query-tests/Exceptions/general/IllegalExceptionHandlerType.qlref
+++ b/python/ql/test/2/query-tests/Exceptions/general/IllegalExceptionHandlerType.qlref
@@ -1 +1,2 @@
-Exceptions/IllegalExceptionHandlerType.ql
\ No newline at end of file
+query: Exceptions/IllegalExceptionHandlerType.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/2/query-tests/Exceptions/general/IllegalRaise.qlref b/python/ql/test/2/query-tests/Exceptions/general/IllegalRaise.qlref
index 5a515d5656d..2bee772260a 100644
--- a/python/ql/test/2/query-tests/Exceptions/general/IllegalRaise.qlref
+++ b/python/ql/test/2/query-tests/Exceptions/general/IllegalRaise.qlref
@@ -1 +1,2 @@
-Exceptions/IllegalRaise.ql
\ No newline at end of file
+query: Exceptions/IllegalRaise.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/2/query-tests/Exceptions/general/IncorrectExceptOrder.qlref b/python/ql/test/2/query-tests/Exceptions/general/IncorrectExceptOrder.qlref
index bc4c3a07081..f4278558baa 100644
--- a/python/ql/test/2/query-tests/Exceptions/general/IncorrectExceptOrder.qlref
+++ b/python/ql/test/2/query-tests/Exceptions/general/IncorrectExceptOrder.qlref
@@ -1 +1,2 @@
-Exceptions/IncorrectExceptOrder.ql
+query: Exceptions/IncorrectExceptOrder.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/2/query-tests/Exceptions/general/exceptions_test.py b/python/ql/test/2/query-tests/Exceptions/general/exceptions_test.py
index 6e82bc02890..023b490eaae 100644
--- a/python/ql/test/2/query-tests/Exceptions/general/exceptions_test.py
+++ b/python/ql/test/2/query-tests/Exceptions/general/exceptions_test.py
@@ -14,4 +14,4 @@ def raise_tuple(cond):
raise (Exception, "bananas", 17)
else:
#This is an error
- raise (17, "bananas", Exception)
+ raise (17, "bananas", Exception) # $ Alert[py/illegal-raise]
diff --git a/python/ql/test/2/query-tests/Exceptions/generators/UnguardedNextInGenerator.qlref b/python/ql/test/2/query-tests/Exceptions/generators/UnguardedNextInGenerator.qlref
index 7fe5d609705..f174a4a96f5 100644
--- a/python/ql/test/2/query-tests/Exceptions/generators/UnguardedNextInGenerator.qlref
+++ b/python/ql/test/2/query-tests/Exceptions/generators/UnguardedNextInGenerator.qlref
@@ -1 +1,2 @@
-Exceptions/UnguardedNextInGenerator.ql
\ No newline at end of file
+query: Exceptions/UnguardedNextInGenerator.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/2/query-tests/Exceptions/generators/test.py b/python/ql/test/2/query-tests/Exceptions/generators/test.py
index e8b3f0b2b34..0c5ca29f798 100644
--- a/python/ql/test/2/query-tests/Exceptions/generators/test.py
+++ b/python/ql/test/2/query-tests/Exceptions/generators/test.py
@@ -2,12 +2,12 @@
def bad1(it):
while True:
- yield next(it)
+ yield next(it) # $ Alert
def bad2(seq):
it = iter(seq)
#Not OK as seq may be empty
- raise KeyError(next(it))
+ raise KeyError(next(it)) # $ Alert
yield 0
def ok1(seq):
diff --git a/python/ql/test/2/query-tests/Exceptions/raising/RaisingTuple.qlref b/python/ql/test/2/query-tests/Exceptions/raising/RaisingTuple.qlref
index 55d1f5e1d4f..1cefef85d8a 100644
--- a/python/ql/test/2/query-tests/Exceptions/raising/RaisingTuple.qlref
+++ b/python/ql/test/2/query-tests/Exceptions/raising/RaisingTuple.qlref
@@ -1 +1,2 @@
-Exceptions/RaisingTuple.ql
+query: Exceptions/RaisingTuple.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/2/query-tests/Exceptions/raising/test.py b/python/ql/test/2/query-tests/Exceptions/raising/test.py
index ff991f642e2..1e5f3cb35fc 100644
--- a/python/ql/test/2/query-tests/Exceptions/raising/test.py
+++ b/python/ql/test/2/query-tests/Exceptions/raising/test.py
@@ -5,11 +5,11 @@ def ok():
def bad1():
ex = Exception, "message"
- raise ex
+ raise ex # $ Alert
def bad2():
- raise (Exception, "message")
+ raise (Exception, "message") # $ Alert
def bad3():
ex = Exception,
- raise ex, "message"
+ raise ex, "message" # $ Alert
diff --git a/python/ql/test/2/query-tests/Expressions/TruncatedDivision.qlref b/python/ql/test/2/query-tests/Expressions/TruncatedDivision.qlref
index fa2c2cbf006..17d539c3226 100644
--- a/python/ql/test/2/query-tests/Expressions/TruncatedDivision.qlref
+++ b/python/ql/test/2/query-tests/Expressions/TruncatedDivision.qlref
@@ -1 +1,2 @@
-Expressions/TruncatedDivision.ql
+query: Expressions/TruncatedDivision.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/2/query-tests/Expressions/TruncatedDivision_test.py b/python/ql/test/2/query-tests/Expressions/TruncatedDivision_test.py
index 6f265b824fb..64ef262edb8 100644
--- a/python/ql/test/2/query-tests/Expressions/TruncatedDivision_test.py
+++ b/python/ql/test/2/query-tests/Expressions/TruncatedDivision_test.py
@@ -62,14 +62,14 @@ print(average([1.0, 2.0]))
# This case is bad, and is a minimal obvious case that should be bad. It
# SHOULD be found by the query.
-print(3 / 2)
+print(3 / 2) # $ Alert[py/truncated-division]
# This case is bad. It uses indirect returns of integers through function calls
# to produce the problem. I
-print(return_three() / return_two())
+print(return_three() / return_two()) # $ Alert[py/truncated-division]
diff --git a/python/ql/test/2/query-tests/Expressions/UseofApply.py b/python/ql/test/2/query-tests/Expressions/UseofApply.py
index 9109636f99e..6c2255012e6 100644
--- a/python/ql/test/2/query-tests/Expressions/UseofApply.py
+++ b/python/ql/test/2/query-tests/Expressions/UseofApply.py
@@ -16,7 +16,7 @@ def useofapply():
# This use of `apply` is a reference to the builtin function and so SHOULD be
# caught by the query.
- apply(foo, [1])
+ apply(foo, [1]) # $ Alert[py/use-of-apply]
diff --git a/python/ql/test/2/query-tests/Expressions/UseofApply.qlref b/python/ql/test/2/query-tests/Expressions/UseofApply.qlref
index abf684e3918..4add79acdb3 100644
--- a/python/ql/test/2/query-tests/Expressions/UseofApply.qlref
+++ b/python/ql/test/2/query-tests/Expressions/UseofApply.qlref
@@ -1 +1,2 @@
-Expressions/UseofApply.ql
+query: Expressions/UseofApply.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/2/query-tests/Expressions/UseofInput.qlref b/python/ql/test/2/query-tests/Expressions/UseofInput.qlref
index 3f9590f48b2..2684126de5e 100644
--- a/python/ql/test/2/query-tests/Expressions/UseofInput.qlref
+++ b/python/ql/test/2/query-tests/Expressions/UseofInput.qlref
@@ -1 +1,2 @@
-Expressions/UseofInput.ql
\ No newline at end of file
+query: Expressions/UseofInput.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/2/query-tests/Expressions/expressions_test.py b/python/ql/test/2/query-tests/Expressions/expressions_test.py
index c31681e3535..5d6c1b89904 100644
--- a/python/ql/test/2/query-tests/Expressions/expressions_test.py
+++ b/python/ql/test/2/query-tests/Expressions/expressions_test.py
@@ -1,9 +1,9 @@
def use_of_apply(func, args):
- apply(func, args)
+ apply(func, args) # $ Alert[py/use-of-apply]
def use_of_input():
- return input() # NOT OK
+ return input() # NOT OK # $ Alert[py/use-of-input]
def not_use_of_input():
diff --git a/python/ql/test/2/query-tests/Functions/DeprecatedSliceMethod.qlref b/python/ql/test/2/query-tests/Functions/DeprecatedSliceMethod.qlref
index c38b8d1f761..3043411c1ce 100644
--- a/python/ql/test/2/query-tests/Functions/DeprecatedSliceMethod.qlref
+++ b/python/ql/test/2/query-tests/Functions/DeprecatedSliceMethod.qlref
@@ -1 +1,2 @@
-Functions/DeprecatedSliceMethod.ql
\ No newline at end of file
+query: Functions/DeprecatedSliceMethod.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/2/query-tests/Imports/encoding_error/EncodingError.qlref b/python/ql/test/2/query-tests/Imports/encoding_error/EncodingError.qlref
index a7e91769ded..bc78d28db32 100644
--- a/python/ql/test/2/query-tests/Imports/encoding_error/EncodingError.qlref
+++ b/python/ql/test/2/query-tests/Imports/encoding_error/EncodingError.qlref
@@ -1 +1,2 @@
-Imports/EncodingError.ql
+query: Imports/EncodingError.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/2/query-tests/Imports/syntax_error/EncodingError.qlref b/python/ql/test/2/query-tests/Imports/syntax_error/EncodingError.qlref
index e742356f865..bc78d28db32 100644
--- a/python/ql/test/2/query-tests/Imports/syntax_error/EncodingError.qlref
+++ b/python/ql/test/2/query-tests/Imports/syntax_error/EncodingError.qlref
@@ -1 +1,2 @@
-Imports/EncodingError.ql
\ No newline at end of file
+query: Imports/EncodingError.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/2/query-tests/Imports/syntax_error/SyntaxError.qlref b/python/ql/test/2/query-tests/Imports/syntax_error/SyntaxError.qlref
index c143a01fe8b..5d0698be3de 100644
--- a/python/ql/test/2/query-tests/Imports/syntax_error/SyntaxError.qlref
+++ b/python/ql/test/2/query-tests/Imports/syntax_error/SyntaxError.qlref
@@ -1 +1,2 @@
-Imports/SyntaxError.ql
\ No newline at end of file
+query: Imports/SyntaxError.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/2/query-tests/Imports/syntax_error/bad_encoding.py b/python/ql/test/2/query-tests/Imports/syntax_error/bad_encoding.py
index 9c61b1e1b11..5e3308df0f5 100644
--- a/python/ql/test/2/query-tests/Imports/syntax_error/bad_encoding.py
+++ b/python/ql/test/2/query-tests/Imports/syntax_error/bad_encoding.py
@@ -8,5 +8,5 @@
# encoding:shift-jis
def f():
- print "Python の開発は、1990 年ごろから開始されています"
+ print "Python の開発は、1990 年ごろから開始されています" # $ Alert[py/encoding-error]
"""
diff --git a/python/ql/test/2/query-tests/Imports/syntax_error/nonsense.py b/python/ql/test/2/query-tests/Imports/syntax_error/nonsense.py
index e413967af41..f5cd27b313b 100644
--- a/python/ql/test/2/query-tests/Imports/syntax_error/nonsense.py
+++ b/python/ql/test/2/query-tests/Imports/syntax_error/nonsense.py
@@ -1,4 +1,4 @@
-`Twas brillig, and the slithy toves
+`Twas brillig, and the slithy toves # $ Alert[py/syntax-error]
Did gyre and gimble in the wabe:
All mimsy were the borogoves,
And the mome raths outgrabe.
diff --git a/python/ql/test/2/query-tests/Lexical/OldOctalLiteral.qlref b/python/ql/test/2/query-tests/Lexical/OldOctalLiteral.qlref
index 40040c873d6..e5b4fdfec57 100644
--- a/python/ql/test/2/query-tests/Lexical/OldOctalLiteral.qlref
+++ b/python/ql/test/2/query-tests/Lexical/OldOctalLiteral.qlref
@@ -1 +1,2 @@
-Lexical/OldOctalLiteral.ql
\ No newline at end of file
+query: Lexical/OldOctalLiteral.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/2/query-tests/Lexical/lexical_test.py b/python/ql/test/2/query-tests/Lexical/lexical_test.py
index 4b82b17cc65..412c24683d1 100644
--- a/python/ql/test/2/query-tests/Lexical/lexical_test.py
+++ b/python/ql/test/2/query-tests/Lexical/lexical_test.py
@@ -1,6 +1,6 @@
#Bad Octal literal
-017
+017 # $ Alert
#Good Octal literal
0o17
#Special case file permissions
diff --git a/python/ql/test/2/query-tests/Statements/ExecUsed.qlref b/python/ql/test/2/query-tests/Statements/ExecUsed.qlref
index ccff89d6815..286996305ed 100644
--- a/python/ql/test/2/query-tests/Statements/ExecUsed.qlref
+++ b/python/ql/test/2/query-tests/Statements/ExecUsed.qlref
@@ -1 +1,2 @@
-Statements/ExecUsed.ql
\ No newline at end of file
+query: Statements/ExecUsed.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/2/query-tests/Statements/IterableStringOrSequence.qlref b/python/ql/test/2/query-tests/Statements/IterableStringOrSequence.qlref
index e8f1ce1b79e..c24806ccf30 100644
--- a/python/ql/test/2/query-tests/Statements/IterableStringOrSequence.qlref
+++ b/python/ql/test/2/query-tests/Statements/IterableStringOrSequence.qlref
@@ -1 +1,2 @@
-Statements/IterableStringOrSequence.ql
\ No newline at end of file
+query: Statements/IterableStringOrSequence.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/2/query-tests/Statements/TopLevelPrint.qlref b/python/ql/test/2/query-tests/Statements/TopLevelPrint.qlref
index 8271065261d..e91717901f3 100644
--- a/python/ql/test/2/query-tests/Statements/TopLevelPrint.qlref
+++ b/python/ql/test/2/query-tests/Statements/TopLevelPrint.qlref
@@ -1 +1,2 @@
-Statements/TopLevelPrint.ql
\ No newline at end of file
+query: Statements/TopLevelPrint.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/2/query-tests/Statements/module.py b/python/ql/test/2/query-tests/Statements/module.py
index 0b1f4d26546..af34eedf0dc 100644
--- a/python/ql/test/2/query-tests/Statements/module.py
+++ b/python/ql/test/2/query-tests/Statements/module.py
@@ -1,2 +1,2 @@
#Top level prints in modules are bad
-print ("Side effect on import")
\ No newline at end of file
+print ("Side effect on import") # $ Alert[py/print-during-import]
\ No newline at end of file
diff --git a/python/ql/test/2/query-tests/Statements/statements_test.py b/python/ql/test/2/query-tests/Statements/statements_test.py
index e540608964d..729b1fd7616 100644
--- a/python/ql/test/2/query-tests/Statements/statements_test.py
+++ b/python/ql/test/2/query-tests/Statements/statements_test.py
@@ -2,7 +2,7 @@
def exec_used(val):
- exec (val)
+ exec (val) # $ Alert[py/use-of-exec]
#Top level print
import module
@@ -18,7 +18,7 @@ def f(x):
s = u"Hello World"
else:
s = [ u'Hello', u'World']
- for thing in s:
+ for thing in s: # $ Alert[py/iteration-string-and-sequence]
print (thing)
import fake_six
diff --git a/python/ql/test/2/query-tests/Summary/LinesOfCode.qlref b/python/ql/test/2/query-tests/Summary/LinesOfCode.qlref
index b60eb791722..d22b1004423 100644
--- a/python/ql/test/2/query-tests/Summary/LinesOfCode.qlref
+++ b/python/ql/test/2/query-tests/Summary/LinesOfCode.qlref
@@ -1 +1 @@
-Summary/LinesOfCode.ql
+query: Summary/LinesOfCode.ql
diff --git a/python/ql/test/2/query-tests/Summary/LinesOfUserCode.qlref b/python/ql/test/2/query-tests/Summary/LinesOfUserCode.qlref
index baaa947e6af..99a6d132494 100644
--- a/python/ql/test/2/query-tests/Summary/LinesOfUserCode.qlref
+++ b/python/ql/test/2/query-tests/Summary/LinesOfUserCode.qlref
@@ -1 +1 @@
-Summary/LinesOfUserCode.ql
+query: Summary/LinesOfUserCode.ql
diff --git a/python/ql/test/2/query-tests/Variables/LeakyComp/LeakyComp.qlref b/python/ql/test/2/query-tests/Variables/LeakyComp/LeakyComp.qlref
index 0f6dd50a281..6b4ece7f127 100644
--- a/python/ql/test/2/query-tests/Variables/LeakyComp/LeakyComp.qlref
+++ b/python/ql/test/2/query-tests/Variables/LeakyComp/LeakyComp.qlref
@@ -1 +1,2 @@
-Variables/LeakingListComprehension.ql
\ No newline at end of file
+query: Variables/LeakingListComprehension.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/2/query-tests/Variables/LeakyComp/test.py b/python/ql/test/2/query-tests/Variables/LeakyComp/test.py
index 0cd6a0d2520..bbb5d33328f 100644
--- a/python/ql/test/2/query-tests/Variables/LeakyComp/test.py
+++ b/python/ql/test/2/query-tests/Variables/LeakyComp/test.py
@@ -2,12 +2,12 @@ from __future__ import print_function
def undefined_in_3():
[x for x in range(3)]
- print(x)
+ print(x) # $ Alert
def different_in_3():
y = 10
[y for y in range(3)]
- print(y)
+ print(y) # $ Alert
def ok():
[z for z in range(4)]
diff --git a/python/ql/test/2/query-tests/Variables/undefined/UndefinedExport.py b/python/ql/test/2/query-tests/Variables/undefined/UndefinedExport.py
index d7ec86a2256..847d0ce4f8e 100644
--- a/python/ql/test/2/query-tests/Variables/undefined/UndefinedExport.py
+++ b/python/ql/test/2/query-tests/Variables/undefined/UndefinedExport.py
@@ -1,6 +1,6 @@
-__all__ = [ "x", "y", "z", "module" ]
+__all__ = [ "x", "y", "z", "module" ] # $ Alert[py/undefined-export]
x = 1
if 0:
diff --git a/python/ql/test/2/query-tests/Variables/undefined/UndefinedExport.qlref b/python/ql/test/2/query-tests/Variables/undefined/UndefinedExport.qlref
index 3e5d31e4748..d964148077e 100644
--- a/python/ql/test/2/query-tests/Variables/undefined/UndefinedExport.qlref
+++ b/python/ql/test/2/query-tests/Variables/undefined/UndefinedExport.qlref
@@ -1 +1,2 @@
-Variables/UndefinedExport.ql
+query: Variables/UndefinedExport.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/2/query-tests/Variables/undefined/UndefinedGlobal.qlref b/python/ql/test/2/query-tests/Variables/undefined/UndefinedGlobal.qlref
index ea9f5a03842..e69631e746b 100644
--- a/python/ql/test/2/query-tests/Variables/undefined/UndefinedGlobal.qlref
+++ b/python/ql/test/2/query-tests/Variables/undefined/UndefinedGlobal.qlref
@@ -1 +1,2 @@
-Variables/UndefinedGlobal.ql
+query: Variables/UndefinedGlobal.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/2/query-tests/Variables/undefined/UninitializedLocal.qlref b/python/ql/test/2/query-tests/Variables/undefined/UninitializedLocal.qlref
index f2d0e603554..90233ce6188 100644
--- a/python/ql/test/2/query-tests/Variables/undefined/UninitializedLocal.qlref
+++ b/python/ql/test/2/query-tests/Variables/undefined/UninitializedLocal.qlref
@@ -1 +1,2 @@
-Variables/UninitializedLocal.ql
+query: Variables/UninitializedLocal.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/2/query-tests/Variables/undefined/package/__init__.py b/python/ql/test/2/query-tests/Variables/undefined/package/__init__.py
index 85f1f2ac24f..d0f80d5e890 100644
--- a/python/ql/test/2/query-tests/Variables/undefined/package/__init__.py
+++ b/python/ql/test/2/query-tests/Variables/undefined/package/__init__.py
@@ -1 +1 @@
-__all__ = [ "module", "not_exists" ]
\ No newline at end of file
+__all__ = [ "module", "not_exists" ] # $ Alert[py/undefined-export]
\ No newline at end of file
diff --git a/python/ql/test/3/query-tests/Classes/equals-attr/DefineEqualsWhenAddingAttributes.qlref b/python/ql/test/3/query-tests/Classes/equals-attr/DefineEqualsWhenAddingAttributes.qlref
index e542a6176ad..f3385f506bf 100644
--- a/python/ql/test/3/query-tests/Classes/equals-attr/DefineEqualsWhenAddingAttributes.qlref
+++ b/python/ql/test/3/query-tests/Classes/equals-attr/DefineEqualsWhenAddingAttributes.qlref
@@ -1 +1,2 @@
-Classes/DefineEqualsWhenAddingAttributes.ql
\ No newline at end of file
+query: Classes/DefineEqualsWhenAddingAttributes.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/3/query-tests/Classes/equals-attr/test.py b/python/ql/test/3/query-tests/Classes/equals-attr/test.py
index 0ab18d0ad43..b6f3e0eb3be 100644
--- a/python/ql/test/3/query-tests/Classes/equals-attr/test.py
+++ b/python/ql/test/3/query-tests/Classes/equals-attr/test.py
@@ -9,7 +9,7 @@ class RedefineEquals:
def __eq__(self, other):
return other is "Tuesday"
-class C(RedefineEquals):
+class C(RedefineEquals): # $ Alert
def __init__(self, args):
self.a, self.b = args
diff --git a/python/ql/test/3/query-tests/Classes/inconsistent-mro/InconsistentMRO.qlref b/python/ql/test/3/query-tests/Classes/inconsistent-mro/InconsistentMRO.qlref
index f43176f3d7a..e2e9a180ab1 100644
--- a/python/ql/test/3/query-tests/Classes/inconsistent-mro/InconsistentMRO.qlref
+++ b/python/ql/test/3/query-tests/Classes/inconsistent-mro/InconsistentMRO.qlref
@@ -1 +1,2 @@
-Classes/InconsistentMRO.ql
\ No newline at end of file
+query: Classes/InconsistentMRO.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/3/query-tests/Classes/inconsistent-mro/inconsistent_mro.py b/python/ql/test/3/query-tests/Classes/inconsistent-mro/inconsistent_mro.py
index 34677864834..9cb04f1df97 100644
--- a/python/ql/test/3/query-tests/Classes/inconsistent-mro/inconsistent_mro.py
+++ b/python/ql/test/3/query-tests/Classes/inconsistent-mro/inconsistent_mro.py
@@ -6,12 +6,12 @@ class X(object):
class Y(X):
pass
-class Z(X, Y):
+class Z(X, Y): # $ Alert
pass
class O:
pass
#This is OK in Python 2
-class N(object, O):
+class N(object, O): # $ Alert
pass
\ No newline at end of file
diff --git a/python/ql/test/3/query-tests/Classes/undefined-attribute/MaybeUndefinedClassAttribute.qlref b/python/ql/test/3/query-tests/Classes/undefined-attribute/MaybeUndefinedClassAttribute.qlref
index d4986ffc84c..35f6da7add5 100644
--- a/python/ql/test/3/query-tests/Classes/undefined-attribute/MaybeUndefinedClassAttribute.qlref
+++ b/python/ql/test/3/query-tests/Classes/undefined-attribute/MaybeUndefinedClassAttribute.qlref
@@ -1 +1,2 @@
-Classes/MaybeUndefinedClassAttribute.ql
+query: Classes/MaybeUndefinedClassAttribute.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/3/query-tests/Classes/undefined-attribute/UndefinedClassAttribute.qlref b/python/ql/test/3/query-tests/Classes/undefined-attribute/UndefinedClassAttribute.qlref
index 7ac0a3b18b7..f0e8fb72278 100644
--- a/python/ql/test/3/query-tests/Classes/undefined-attribute/UndefinedClassAttribute.qlref
+++ b/python/ql/test/3/query-tests/Classes/undefined-attribute/UndefinedClassAttribute.qlref
@@ -1 +1,2 @@
-Classes/UndefinedClassAttribute.ql
+query: Classes/UndefinedClassAttribute.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/3/query-tests/Expressions/Arguments/WrongNameForArgumentInCall.qlref b/python/ql/test/3/query-tests/Expressions/Arguments/WrongNameForArgumentInCall.qlref
index 3599f204f55..c6b6ca3d30f 100644
--- a/python/ql/test/3/query-tests/Expressions/Arguments/WrongNameForArgumentInCall.qlref
+++ b/python/ql/test/3/query-tests/Expressions/Arguments/WrongNameForArgumentInCall.qlref
@@ -1 +1,2 @@
-Expressions/WrongNameForArgumentInCall.ql
\ No newline at end of file
+query: Expressions/WrongNameForArgumentInCall.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/3/query-tests/Expressions/Arguments/WrongNumberArgumentsInCall.qlref b/python/ql/test/3/query-tests/Expressions/Arguments/WrongNumberArgumentsInCall.qlref
index 1bffe8f1cad..68dc510d5c6 100644
--- a/python/ql/test/3/query-tests/Expressions/Arguments/WrongNumberArgumentsInCall.qlref
+++ b/python/ql/test/3/query-tests/Expressions/Arguments/WrongNumberArgumentsInCall.qlref
@@ -1 +1,2 @@
-Expressions/WrongNumberArgumentsInCall.ql
\ No newline at end of file
+query: Expressions/WrongNumberArgumentsInCall.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/3/query-tests/Expressions/Arguments/wrong_arguments.py b/python/ql/test/3/query-tests/Expressions/Arguments/wrong_arguments.py
index 729177ea0b4..1242af144b6 100644
--- a/python/ql/test/3/query-tests/Expressions/Arguments/wrong_arguments.py
+++ b/python/ql/test/3/query-tests/Expressions/Arguments/wrong_arguments.py
@@ -9,8 +9,8 @@ f(1, 2, 3, kw1=1)
f(1, 2, kw1=1, kw2=2)
#Not OK
-f(1, 2, 3, kw1=1, kw3=3)
-f(1, 2, 3, kw3=3)
+f(1, 2, 3, kw1=1, kw3=3) # $ Alert[py/call/wrong-named-argument]
+f(1, 2, 3, kw3=3) # $ Alert[py/call/wrong-named-argument]
#ODASA-5897
@@ -21,4 +21,4 @@ def ok():
return analyze_member_access(msg, original=original, chk=chk)
def bad():
- return analyze_member_access(msg, original, chk=chk)
+ return analyze_member_access(msg, original, chk=chk) # $ Alert[py/call/wrong-arguments]
diff --git a/python/ql/test/3/query-tests/Expressions/Formatting/WrongNumberArgumentsForFormat.qlref b/python/ql/test/3/query-tests/Expressions/Formatting/WrongNumberArgumentsForFormat.qlref
index 0d127e1b618..744334a6aeb 100644
--- a/python/ql/test/3/query-tests/Expressions/Formatting/WrongNumberArgumentsForFormat.qlref
+++ b/python/ql/test/3/query-tests/Expressions/Formatting/WrongNumberArgumentsForFormat.qlref
@@ -1 +1,2 @@
-Expressions/WrongNumberArgumentsForFormat.ql
\ No newline at end of file
+query: Expressions/WrongNumberArgumentsForFormat.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/3/query-tests/Expressions/TruncatedDivision/TruncatedDivision.qlref b/python/ql/test/3/query-tests/Expressions/TruncatedDivision/TruncatedDivision.qlref
index fa2c2cbf006..17d539c3226 100644
--- a/python/ql/test/3/query-tests/Expressions/TruncatedDivision/TruncatedDivision.qlref
+++ b/python/ql/test/3/query-tests/Expressions/TruncatedDivision/TruncatedDivision.qlref
@@ -1 +1,2 @@
-Expressions/TruncatedDivision.ql
+query: Expressions/TruncatedDivision.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/3/query-tests/Expressions/UseofApply/UseofApply.qlref b/python/ql/test/3/query-tests/Expressions/UseofApply/UseofApply.qlref
index abf684e3918..4add79acdb3 100644
--- a/python/ql/test/3/query-tests/Expressions/UseofApply/UseofApply.qlref
+++ b/python/ql/test/3/query-tests/Expressions/UseofApply/UseofApply.qlref
@@ -1 +1,2 @@
-Expressions/UseofApply.ql
+query: Expressions/UseofApply.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/3/query-tests/Imports/encoding_error/EncodingError.qlref b/python/ql/test/3/query-tests/Imports/encoding_error/EncodingError.qlref
index a7e91769ded..bc78d28db32 100644
--- a/python/ql/test/3/query-tests/Imports/encoding_error/EncodingError.qlref
+++ b/python/ql/test/3/query-tests/Imports/encoding_error/EncodingError.qlref
@@ -1 +1,2 @@
-Imports/EncodingError.ql
+query: Imports/EncodingError.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/3/query-tests/Imports/syntax_error/EncodingError.qlref b/python/ql/test/3/query-tests/Imports/syntax_error/EncodingError.qlref
index e742356f865..bc78d28db32 100644
--- a/python/ql/test/3/query-tests/Imports/syntax_error/EncodingError.qlref
+++ b/python/ql/test/3/query-tests/Imports/syntax_error/EncodingError.qlref
@@ -1 +1,2 @@
-Imports/EncodingError.ql
\ No newline at end of file
+query: Imports/EncodingError.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/3/query-tests/Imports/syntax_error/SyntaxError.qlref b/python/ql/test/3/query-tests/Imports/syntax_error/SyntaxError.qlref
index c143a01fe8b..5d0698be3de 100644
--- a/python/ql/test/3/query-tests/Imports/syntax_error/SyntaxError.qlref
+++ b/python/ql/test/3/query-tests/Imports/syntax_error/SyntaxError.qlref
@@ -1 +1,2 @@
-Imports/SyntaxError.ql
\ No newline at end of file
+query: Imports/SyntaxError.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/3/query-tests/Imports/syntax_error/bad_encoding.py b/python/ql/test/3/query-tests/Imports/syntax_error/bad_encoding.py
index 9c61b1e1b11..5e3308df0f5 100644
--- a/python/ql/test/3/query-tests/Imports/syntax_error/bad_encoding.py
+++ b/python/ql/test/3/query-tests/Imports/syntax_error/bad_encoding.py
@@ -8,5 +8,5 @@
# encoding:shift-jis
def f():
- print "Python の開発は、1990 年ごろから開始されています"
+ print "Python の開発は、1990 年ごろから開始されています" # $ Alert[py/encoding-error]
"""
diff --git a/python/ql/test/3/query-tests/Imports/syntax_error/nonsense.py b/python/ql/test/3/query-tests/Imports/syntax_error/nonsense.py
index 66cdd526fba..e0819afbc5e 100644
--- a/python/ql/test/3/query-tests/Imports/syntax_error/nonsense.py
+++ b/python/ql/test/3/query-tests/Imports/syntax_error/nonsense.py
@@ -1,4 +1,4 @@
- `Twas brillig, and the slithy toves
+ `Twas brillig, and the slithy toves # $ Alert[py/syntax-error]
Did gyre and gimble in the wabe:
All mimsy were the borogoves,
And the mome raths outgrabe.
diff --git a/python/ql/test/3/query-tests/Statements/general/ExecUsed.qlref b/python/ql/test/3/query-tests/Statements/general/ExecUsed.qlref
index ccff89d6815..286996305ed 100644
--- a/python/ql/test/3/query-tests/Statements/general/ExecUsed.qlref
+++ b/python/ql/test/3/query-tests/Statements/general/ExecUsed.qlref
@@ -1 +1,2 @@
-Statements/ExecUsed.ql
\ No newline at end of file
+query: Statements/ExecUsed.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/3/query-tests/Statements/general/TopLevelPrint.qlref b/python/ql/test/3/query-tests/Statements/general/TopLevelPrint.qlref
index 8271065261d..e91717901f3 100644
--- a/python/ql/test/3/query-tests/Statements/general/TopLevelPrint.qlref
+++ b/python/ql/test/3/query-tests/Statements/general/TopLevelPrint.qlref
@@ -1 +1,2 @@
-Statements/TopLevelPrint.ql
\ No newline at end of file
+query: Statements/TopLevelPrint.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/3/query-tests/Statements/general/module.py b/python/ql/test/3/query-tests/Statements/general/module.py
index 0b1f4d26546..af34eedf0dc 100644
--- a/python/ql/test/3/query-tests/Statements/general/module.py
+++ b/python/ql/test/3/query-tests/Statements/general/module.py
@@ -1,2 +1,2 @@
#Top level prints in modules are bad
-print ("Side effect on import")
\ No newline at end of file
+print ("Side effect on import") # $ Alert[py/print-during-import]
\ No newline at end of file
diff --git a/python/ql/test/3/query-tests/Statements/general/statements_test.py b/python/ql/test/3/query-tests/Statements/general/statements_test.py
index 2baee458c04..a4414a40f80 100644
--- a/python/ql/test/3/query-tests/Statements/general/statements_test.py
+++ b/python/ql/test/3/query-tests/Statements/general/statements_test.py
@@ -2,7 +2,7 @@
def exec_used(val):
- exec(val)
+ exec(val) # $ Alert[py/use-of-exec]
#Top level print
import module
diff --git a/python/ql/test/3/query-tests/Statements/iter/IterableStringOrSequence.qlref b/python/ql/test/3/query-tests/Statements/iter/IterableStringOrSequence.qlref
index e8f1ce1b79e..c24806ccf30 100644
--- a/python/ql/test/3/query-tests/Statements/iter/IterableStringOrSequence.qlref
+++ b/python/ql/test/3/query-tests/Statements/iter/IterableStringOrSequence.qlref
@@ -1 +1,2 @@
-Statements/IterableStringOrSequence.ql
\ No newline at end of file
+query: Statements/IterableStringOrSequence.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/3/query-tests/Statements/iter/NonIteratorInForLoop.qlref b/python/ql/test/3/query-tests/Statements/iter/NonIteratorInForLoop.qlref
index fb09cace29a..b7697d64d8f 100644
--- a/python/ql/test/3/query-tests/Statements/iter/NonIteratorInForLoop.qlref
+++ b/python/ql/test/3/query-tests/Statements/iter/NonIteratorInForLoop.qlref
@@ -1 +1,2 @@
-Statements/NonIteratorInForLoop.ql
\ No newline at end of file
+query: Statements/NonIteratorInForLoop.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/3/query-tests/Statements/iter/async_iterator.py b/python/ql/test/3/query-tests/Statements/iter/async_iterator.py
index fdde931eace..76972058a02 100644
--- a/python/ql/test/3/query-tests/Statements/iter/async_iterator.py
+++ b/python/ql/test/3/query-tests/Statements/iter/async_iterator.py
@@ -23,5 +23,5 @@ async def good():
yield x
async def bad():
- async for x in MissingAiter():
+ async for x in MissingAiter(): # $ Alert[py/non-iterable-in-for-loop]
yield x
diff --git a/python/ql/test/3/query-tests/Statements/iter/statements_test.py b/python/ql/test/3/query-tests/Statements/iter/statements_test.py
index 33b3f4aae5c..daf811f3f83 100644
--- a/python/ql/test/3/query-tests/Statements/iter/statements_test.py
+++ b/python/ql/test/3/query-tests/Statements/iter/statements_test.py
@@ -18,7 +18,7 @@ def f(x):
s = u"Hello World"
else:
s = [ u'Hello', u'World']
- for thing in s:
+ for thing in s: # $ Alert[py/iteration-string-and-sequence]
print (thing)
@@ -31,7 +31,7 @@ class Color(Enum):
def colors():
for color in Color:
print(color)
- for color in 1:
+ for color in 1: # $ Alert[py/non-iterable-in-for-loop]
print(color)
colors()
diff --git a/python/ql/test/3/query-tests/Statements/unreachable/UnreachableCode.qlref b/python/ql/test/3/query-tests/Statements/unreachable/UnreachableCode.qlref
index 5b7891f0026..b95a67d2494 100644
--- a/python/ql/test/3/query-tests/Statements/unreachable/UnreachableCode.qlref
+++ b/python/ql/test/3/query-tests/Statements/unreachable/UnreachableCode.qlref
@@ -1 +1,2 @@
-Statements/UnreachableCode.ql
+query: Statements/UnreachableCode.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/3/query-tests/Statements/unreachable_suppressed/UnreachableCode.qlref b/python/ql/test/3/query-tests/Statements/unreachable_suppressed/UnreachableCode.qlref
index 5b7891f0026..b95a67d2494 100644
--- a/python/ql/test/3/query-tests/Statements/unreachable_suppressed/UnreachableCode.qlref
+++ b/python/ql/test/3/query-tests/Statements/unreachable_suppressed/UnreachableCode.qlref
@@ -1 +1,2 @@
-Statements/UnreachableCode.ql
+query: Statements/UnreachableCode.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/3/query-tests/Summary/LinesOfCode.qlref b/python/ql/test/3/query-tests/Summary/LinesOfCode.qlref
index b60eb791722..d22b1004423 100644
--- a/python/ql/test/3/query-tests/Summary/LinesOfCode.qlref
+++ b/python/ql/test/3/query-tests/Summary/LinesOfCode.qlref
@@ -1 +1 @@
-Summary/LinesOfCode.ql
+query: Summary/LinesOfCode.ql
diff --git a/python/ql/test/3/query-tests/Summary/LinesOfUserCode.qlref b/python/ql/test/3/query-tests/Summary/LinesOfUserCode.qlref
index baaa947e6af..99a6d132494 100644
--- a/python/ql/test/3/query-tests/Summary/LinesOfUserCode.qlref
+++ b/python/ql/test/3/query-tests/Summary/LinesOfUserCode.qlref
@@ -1 +1 @@
-Summary/LinesOfUserCode.ql
+query: Summary/LinesOfUserCode.ql
diff --git a/python/ql/test/3/query-tests/Variables/undefined/UndefinedExport.py b/python/ql/test/3/query-tests/Variables/undefined/UndefinedExport.py
index fc1a03f6e1c..84a717c0314 100644
--- a/python/ql/test/3/query-tests/Variables/undefined/UndefinedExport.py
+++ b/python/ql/test/3/query-tests/Variables/undefined/UndefinedExport.py
@@ -1,6 +1,6 @@
-__all__ = [ "x", "y", "z", "module", "w" ]
+__all__ = [ "x", "y", "z", "module", "w" ] # $ Alert[py/undefined-export]
x = 1
if 0:
diff --git a/python/ql/test/3/query-tests/Variables/undefined/UndefinedExport.qlref b/python/ql/test/3/query-tests/Variables/undefined/UndefinedExport.qlref
index 3e5d31e4748..d964148077e 100644
--- a/python/ql/test/3/query-tests/Variables/undefined/UndefinedExport.qlref
+++ b/python/ql/test/3/query-tests/Variables/undefined/UndefinedExport.qlref
@@ -1 +1,2 @@
-Variables/UndefinedExport.ql
+query: Variables/UndefinedExport.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/3/query-tests/Variables/undefined/UninitializedLocal.qlref b/python/ql/test/3/query-tests/Variables/undefined/UninitializedLocal.qlref
index f2d0e603554..90233ce6188 100644
--- a/python/ql/test/3/query-tests/Variables/undefined/UninitializedLocal.qlref
+++ b/python/ql/test/3/query-tests/Variables/undefined/UninitializedLocal.qlref
@@ -1 +1,2 @@
-Variables/UninitializedLocal.ql
+query: Variables/UninitializedLocal.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/3/query-tests/Variables/undefined/enum_convert.py b/python/ql/test/3/query-tests/Variables/undefined/enum_convert.py
index 58979d0b4c9..db6b89b8f7f 100644
--- a/python/ql/test/3/query-tests/Variables/undefined/enum_convert.py
+++ b/python/ql/test/3/query-tests/Variables/undefined/enum_convert.py
@@ -5,4 +5,4 @@ IntEnum._convert(
__name__,
lambda C: C.isupper() and C.startswith('AF_'))
-__all__ = [ "Maybe", "Maybe_not" ]
+__all__ = [ "Maybe", "Maybe_not" ] # $ Alert[py/undefined-export]
diff --git a/python/ql/test/3/query-tests/Variables/undefined/package/__init__.py b/python/ql/test/3/query-tests/Variables/undefined/package/__init__.py
index 85f1f2ac24f..d0f80d5e890 100644
--- a/python/ql/test/3/query-tests/Variables/undefined/package/__init__.py
+++ b/python/ql/test/3/query-tests/Variables/undefined/package/__init__.py
@@ -1 +1 @@
-__all__ = [ "module", "not_exists" ]
\ No newline at end of file
+__all__ = [ "module", "not_exists" ] # $ Alert[py/undefined-export]
\ No newline at end of file
diff --git a/python/ql/test/experimental/library-tests/CallGraph-implicit-init/InlineCallGraphTest.qlref b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/InlineCallGraphTest.qlref
index 25117a4582b..e7b837c8900 100644
--- a/python/ql/test/experimental/library-tests/CallGraph-implicit-init/InlineCallGraphTest.qlref
+++ b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/InlineCallGraphTest.qlref
@@ -1 +1 @@
-../CallGraph/InlineCallGraphTest.ql
+query: ../CallGraph/InlineCallGraphTest.ql
diff --git a/python/ql/test/experimental/library-tests/CallGraph-imports/InlineCallGraphTest.qlref b/python/ql/test/experimental/library-tests/CallGraph-imports/InlineCallGraphTest.qlref
index 25117a4582b..e7b837c8900 100644
--- a/python/ql/test/experimental/library-tests/CallGraph-imports/InlineCallGraphTest.qlref
+++ b/python/ql/test/experimental/library-tests/CallGraph-imports/InlineCallGraphTest.qlref
@@ -1 +1 @@
-../CallGraph/InlineCallGraphTest.ql
+query: ../CallGraph/InlineCallGraphTest.ql
diff --git a/python/ql/test/experimental/library-tests/CallGraph-type-annotations/InlineCallGraphTest.qlref b/python/ql/test/experimental/library-tests/CallGraph-type-annotations/InlineCallGraphTest.qlref
index 25117a4582b..e7b837c8900 100644
--- a/python/ql/test/experimental/library-tests/CallGraph-type-annotations/InlineCallGraphTest.qlref
+++ b/python/ql/test/experimental/library-tests/CallGraph-type-annotations/InlineCallGraphTest.qlref
@@ -1 +1 @@
-../CallGraph/InlineCallGraphTest.ql
+query: ../CallGraph/InlineCallGraphTest.ql
diff --git a/python/ql/test/experimental/library-tests/FindSubclass/Find.qlref b/python/ql/test/experimental/library-tests/FindSubclass/Find.qlref
index f8bd638be1a..59bdb1462de 100644
--- a/python/ql/test/experimental/library-tests/FindSubclass/Find.qlref
+++ b/python/ql/test/experimental/library-tests/FindSubclass/Find.qlref
@@ -1 +1 @@
-meta/ClassHierarchy/Find.ql
+query: meta/ClassHierarchy/Find.ql
diff --git a/python/ql/test/experimental/query-tests/Classes/Naming/NamingConventionsClasses.py b/python/ql/test/experimental/query-tests/Classes/Naming/NamingConventionsClasses.py
index c07bdb57234..46633a009f7 100644
--- a/python/ql/test/experimental/query-tests/Classes/Naming/NamingConventionsClasses.py
+++ b/python/ql/test/experimental/query-tests/Classes/Naming/NamingConventionsClasses.py
@@ -1,5 +1,5 @@
# BAD, do not start class or interface name with lowercase letter
-class badName:
+class badName: # $ Alert
def hello(self):
print("hello")
diff --git a/python/ql/test/experimental/query-tests/Classes/Naming/NamingConventionsClasses.qlref b/python/ql/test/experimental/query-tests/Classes/Naming/NamingConventionsClasses.qlref
index 7ed945d782c..b5b73c19bf8 100644
--- a/python/ql/test/experimental/query-tests/Classes/Naming/NamingConventionsClasses.qlref
+++ b/python/ql/test/experimental/query-tests/Classes/Naming/NamingConventionsClasses.qlref
@@ -1 +1,2 @@
-experimental/Classes/NamingConventionsClasses.ql
\ No newline at end of file
+query: experimental/Classes/NamingConventionsClasses.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/experimental/query-tests/Functions/general/NamingConventionsFunctions.py b/python/ql/test/experimental/query-tests/Functions/general/NamingConventionsFunctions.py
index fb3e89ab8e9..5923ce5919f 100644
--- a/python/ql/test/experimental/query-tests/Functions/general/NamingConventionsFunctions.py
+++ b/python/ql/test/experimental/query-tests/Functions/general/NamingConventionsFunctions.py
@@ -1,7 +1,7 @@
class Test:
# BAD, do not start function name with uppercase letter
- def HelloWorld(self):
+ def HelloWorld(self): # $ Alert
print("hello world")
# GOOD, function name starts with lowercase letter
diff --git a/python/ql/test/experimental/query-tests/Functions/general/NamingConventionsFunctions.qlref b/python/ql/test/experimental/query-tests/Functions/general/NamingConventionsFunctions.qlref
index 0204694de0a..21d3e5fe135 100644
--- a/python/ql/test/experimental/query-tests/Functions/general/NamingConventionsFunctions.qlref
+++ b/python/ql/test/experimental/query-tests/Functions/general/NamingConventionsFunctions.qlref
@@ -1 +1,2 @@
-experimental/Functions/NamingConventionsFunctions.ql
\ No newline at end of file
+query: experimental/Functions/NamingConventionsFunctions.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/TarSlip.expected b/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/TarSlip.expected
index 6de2b27bfa7..6cceacd031f 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/TarSlip.expected
+++ b/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/TarSlip.expected
@@ -1,3 +1,33 @@
+#select
+| TarSlipImprov.py:22:35:22:40 | ControlFlowNode for result | TarSlipImprov.py:15:7:15:39 | ControlFlowNode for Attribute() | TarSlipImprov.py:22:35:22:40 | ControlFlowNode for result | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:15:7:15:39 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:22:35:22:40 | ControlFlowNode for result | ControlFlowNode for result |
+| TarSlipImprov.py:39:49:39:68 | ControlFlowNode for members_filter1() | TarSlipImprov.py:38:7:38:39 | ControlFlowNode for Attribute() | TarSlipImprov.py:39:49:39:68 | ControlFlowNode for members_filter1() | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:38:7:38:39 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:39:49:39:68 | ControlFlowNode for members_filter1() | ControlFlowNode for members_filter1() |
+| TarSlipImprov.py:47:21:47:25 | ControlFlowNode for entry | TarSlipImprov.py:43:6:43:38 | ControlFlowNode for Attribute() | TarSlipImprov.py:47:21:47:25 | ControlFlowNode for entry | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:43:6:43:38 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:47:21:47:25 | ControlFlowNode for entry | ControlFlowNode for entry |
+| TarSlipImprov.py:58:21:58:25 | ControlFlowNode for entry | TarSlipImprov.py:54:6:54:38 | ControlFlowNode for Attribute() | TarSlipImprov.py:58:21:58:25 | ControlFlowNode for entry | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:54:6:54:38 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:58:21:58:25 | ControlFlowNode for entry | ControlFlowNode for entry |
+| TarSlipImprov.py:91:5:91:7 | ControlFlowNode for tar | TarSlipImprov.py:88:6:88:43 | ControlFlowNode for Attribute() | TarSlipImprov.py:91:5:91:7 | ControlFlowNode for tar | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:88:6:88:43 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:91:5:91:7 | ControlFlowNode for tar | ControlFlowNode for tar |
+| TarSlipImprov.py:115:9:115:11 | ControlFlowNode for tar | TarSlipImprov.py:111:7:111:39 | ControlFlowNode for Attribute() | TarSlipImprov.py:115:9:115:11 | ControlFlowNode for tar | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:111:7:111:39 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:115:9:115:11 | ControlFlowNode for tar | ControlFlowNode for tar |
+| TarSlipImprov.py:125:36:125:40 | ControlFlowNode for entry | TarSlipImprov.py:123:6:123:29 | ControlFlowNode for Attribute() | TarSlipImprov.py:125:36:125:40 | ControlFlowNode for entry | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:123:6:123:29 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:125:36:125:40 | ControlFlowNode for entry | ControlFlowNode for entry |
+| TarSlipImprov.py:130:5:130:7 | ControlFlowNode for tar | TarSlipImprov.py:129:6:129:26 | ControlFlowNode for Attribute() | TarSlipImprov.py:130:5:130:7 | ControlFlowNode for tar | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:129:6:129:26 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:130:5:130:7 | ControlFlowNode for tar | ControlFlowNode for tar |
+| TarSlipImprov.py:134:1:134:3 | ControlFlowNode for tar | TarSlipImprov.py:133:7:133:39 | ControlFlowNode for Attribute() | TarSlipImprov.py:134:1:134:3 | ControlFlowNode for tar | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:133:7:133:39 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:134:1:134:3 | ControlFlowNode for tar | ControlFlowNode for tar |
+| TarSlipImprov.py:143:36:143:40 | ControlFlowNode for entry | TarSlipImprov.py:141:6:141:29 | ControlFlowNode for Attribute() | TarSlipImprov.py:143:36:143:40 | ControlFlowNode for entry | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:141:6:141:29 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:143:36:143:40 | ControlFlowNode for entry | ControlFlowNode for entry |
+| TarSlipImprov.py:169:9:169:12 | ControlFlowNode for tarc | TarSlipImprov.py:151:22:151:49 | ControlFlowNode for Attribute() | TarSlipImprov.py:169:9:169:12 | ControlFlowNode for tarc | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:151:22:151:49 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:169:9:169:12 | ControlFlowNode for tarc | ControlFlowNode for tarc |
+| TarSlipImprov.py:169:9:169:12 | ControlFlowNode for tarc | TarSlipImprov.py:159:26:159:51 | ControlFlowNode for Attribute() | TarSlipImprov.py:169:9:169:12 | ControlFlowNode for tarc | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:159:26:159:51 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:169:9:169:12 | ControlFlowNode for tarc | ControlFlowNode for tarc |
+| TarSlipImprov.py:178:36:178:40 | ControlFlowNode for entry | TarSlipImprov.py:176:6:176:31 | ControlFlowNode for Attribute() | TarSlipImprov.py:178:36:178:40 | ControlFlowNode for entry | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:176:6:176:31 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:178:36:178:40 | ControlFlowNode for entry | ControlFlowNode for entry |
+| TarSlipImprov.py:184:21:184:25 | ControlFlowNode for entry | TarSlipImprov.py:182:6:182:31 | ControlFlowNode for Attribute() | TarSlipImprov.py:184:21:184:25 | ControlFlowNode for entry | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:182:6:182:31 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:184:21:184:25 | ControlFlowNode for entry | ControlFlowNode for entry |
+| TarSlipImprov.py:189:1:189:3 | ControlFlowNode for tar | TarSlipImprov.py:188:7:188:27 | ControlFlowNode for Attribute() | TarSlipImprov.py:189:1:189:3 | ControlFlowNode for tar | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:188:7:188:27 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:189:1:189:3 | ControlFlowNode for tar | ControlFlowNode for tar |
+| TarSlipImprov.py:194:49:194:51 | ControlFlowNode for tar | TarSlipImprov.py:193:6:193:31 | ControlFlowNode for Attribute() | TarSlipImprov.py:194:49:194:51 | ControlFlowNode for tar | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:193:6:193:31 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:194:49:194:51 | ControlFlowNode for tar | ControlFlowNode for tar |
+| TarSlipImprov.py:211:5:211:7 | ControlFlowNode for tar | TarSlipImprov.py:210:6:210:43 | ControlFlowNode for Attribute() | TarSlipImprov.py:211:5:211:7 | ControlFlowNode for tar | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:210:6:210:43 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:211:5:211:7 | ControlFlowNode for tar | ControlFlowNode for tar |
+| TarSlipImprov.py:236:44:236:50 | ControlFlowNode for members | TarSlipImprov.py:231:6:231:38 | ControlFlowNode for Attribute() | TarSlipImprov.py:236:44:236:50 | ControlFlowNode for members | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:231:6:231:38 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:236:44:236:50 | ControlFlowNode for members | ControlFlowNode for members |
+| TarSlipImprov.py:254:1:254:31 | ControlFlowNode for Attribute() | TarSlipImprov.py:254:1:254:31 | ControlFlowNode for Attribute() | TarSlipImprov.py:254:1:254:31 | ControlFlowNode for Attribute() | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:254:1:254:31 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:254:1:254:31 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() |
+| TarSlipImprov.py:261:25:261:29 | ControlFlowNode for entry | TarSlipImprov.py:258:6:258:26 | ControlFlowNode for Attribute() | TarSlipImprov.py:261:25:261:29 | ControlFlowNode for entry | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:258:6:258:26 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:261:25:261:29 | ControlFlowNode for entry | ControlFlowNode for entry |
+| TarSlipImprov.py:268:21:268:25 | ControlFlowNode for entry | TarSlipImprov.py:264:6:264:38 | ControlFlowNode for Attribute() | TarSlipImprov.py:268:21:268:25 | ControlFlowNode for entry | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:264:6:264:38 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:268:21:268:25 | ControlFlowNode for entry | ControlFlowNode for entry |
+| TarSlipImprov.py:274:25:274:29 | ControlFlowNode for entry | TarSlipImprov.py:271:6:271:39 | ControlFlowNode for Attribute() | TarSlipImprov.py:274:25:274:29 | ControlFlowNode for entry | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:271:6:271:39 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:274:25:274:29 | ControlFlowNode for entry | ControlFlowNode for entry |
+| TarSlipImprov.py:280:21:280:25 | ControlFlowNode for entry | TarSlipImprov.py:276:6:276:38 | ControlFlowNode for Attribute() | TarSlipImprov.py:280:21:280:25 | ControlFlowNode for entry | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:276:6:276:38 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:280:21:280:25 | ControlFlowNode for entry | ControlFlowNode for entry |
+| TarSlipImprov.py:284:5:284:7 | ControlFlowNode for tar | TarSlipImprov.py:283:6:283:51 | ControlFlowNode for Attribute() | TarSlipImprov.py:284:5:284:7 | ControlFlowNode for tar | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:283:6:283:51 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:284:5:284:7 | ControlFlowNode for tar | ControlFlowNode for tar |
+| TarSlipImprov.py:288:49:288:51 | ControlFlowNode for tar | TarSlipImprov.py:287:7:287:28 | ControlFlowNode for Attribute() | TarSlipImprov.py:288:49:288:51 | ControlFlowNode for tar | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:287:7:287:28 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:288:49:288:51 | ControlFlowNode for tar | ControlFlowNode for tar |
+| TarSlipImprov.py:293:1:293:3 | ControlFlowNode for tar | TarSlipImprov.py:292:7:292:39 | ControlFlowNode for Attribute() | TarSlipImprov.py:293:1:293:3 | ControlFlowNode for tar | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:292:7:292:39 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:293:1:293:3 | ControlFlowNode for tar | ControlFlowNode for tar |
+| TarSlipImprov.py:301:49:301:51 | ControlFlowNode for tar | TarSlipImprov.py:300:6:300:51 | ControlFlowNode for Attribute() | TarSlipImprov.py:301:49:301:51 | ControlFlowNode for tar | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:300:6:300:51 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:301:49:301:51 | ControlFlowNode for tar | ControlFlowNode for tar |
+| TarSlipImprov.py:310:49:310:54 | ControlFlowNode for result | TarSlipImprov.py:304:7:304:39 | ControlFlowNode for Attribute() | TarSlipImprov.py:310:49:310:54 | ControlFlowNode for result | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:304:7:304:39 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:310:49:310:54 | ControlFlowNode for result | ControlFlowNode for result |
+| TarSlipImprov.py:316:1:316:46 | ControlFlowNode for Attribute() | TarSlipImprov.py:316:1:316:46 | ControlFlowNode for Attribute() | TarSlipImprov.py:316:1:316:46 | ControlFlowNode for Attribute() | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:316:1:316:46 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:316:1:316:46 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() |
edges
| TarSlipImprov.py:15:1:15:3 | ControlFlowNode for tar | TarSlipImprov.py:17:5:17:10 | ControlFlowNode for member | provenance | |
| TarSlipImprov.py:15:7:15:39 | ControlFlowNode for Attribute() | TarSlipImprov.py:15:1:15:3 | ControlFlowNode for tar | provenance | |
@@ -223,33 +253,3 @@ nodes
subpaths
| TarSlipImprov.py:39:65:39:67 | ControlFlowNode for tar | TarSlipImprov.py:26:21:26:27 | ControlFlowNode for tarfile | TarSlipImprov.py:36:12:36:17 | ControlFlowNode for result | TarSlipImprov.py:39:49:39:68 | ControlFlowNode for members_filter1() |
| TarSlipImprov.py:39:65:39:67 | ControlFlowNode for tar | TarSlipImprov.py:26:21:26:27 | ControlFlowNode for tarfile | TarSlipImprov.py:36:12:36:17 | ControlFlowNode for result [List element] | TarSlipImprov.py:39:49:39:68 | ControlFlowNode for members_filter1() |
-#select
-| TarSlipImprov.py:22:35:22:40 | ControlFlowNode for result | TarSlipImprov.py:15:7:15:39 | ControlFlowNode for Attribute() | TarSlipImprov.py:22:35:22:40 | ControlFlowNode for result | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:15:7:15:39 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:22:35:22:40 | ControlFlowNode for result | ControlFlowNode for result |
-| TarSlipImprov.py:39:49:39:68 | ControlFlowNode for members_filter1() | TarSlipImprov.py:38:7:38:39 | ControlFlowNode for Attribute() | TarSlipImprov.py:39:49:39:68 | ControlFlowNode for members_filter1() | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:38:7:38:39 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:39:49:39:68 | ControlFlowNode for members_filter1() | ControlFlowNode for members_filter1() |
-| TarSlipImprov.py:47:21:47:25 | ControlFlowNode for entry | TarSlipImprov.py:43:6:43:38 | ControlFlowNode for Attribute() | TarSlipImprov.py:47:21:47:25 | ControlFlowNode for entry | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:43:6:43:38 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:47:21:47:25 | ControlFlowNode for entry | ControlFlowNode for entry |
-| TarSlipImprov.py:58:21:58:25 | ControlFlowNode for entry | TarSlipImprov.py:54:6:54:38 | ControlFlowNode for Attribute() | TarSlipImprov.py:58:21:58:25 | ControlFlowNode for entry | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:54:6:54:38 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:58:21:58:25 | ControlFlowNode for entry | ControlFlowNode for entry |
-| TarSlipImprov.py:91:5:91:7 | ControlFlowNode for tar | TarSlipImprov.py:88:6:88:43 | ControlFlowNode for Attribute() | TarSlipImprov.py:91:5:91:7 | ControlFlowNode for tar | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:88:6:88:43 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:91:5:91:7 | ControlFlowNode for tar | ControlFlowNode for tar |
-| TarSlipImprov.py:115:9:115:11 | ControlFlowNode for tar | TarSlipImprov.py:111:7:111:39 | ControlFlowNode for Attribute() | TarSlipImprov.py:115:9:115:11 | ControlFlowNode for tar | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:111:7:111:39 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:115:9:115:11 | ControlFlowNode for tar | ControlFlowNode for tar |
-| TarSlipImprov.py:125:36:125:40 | ControlFlowNode for entry | TarSlipImprov.py:123:6:123:29 | ControlFlowNode for Attribute() | TarSlipImprov.py:125:36:125:40 | ControlFlowNode for entry | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:123:6:123:29 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:125:36:125:40 | ControlFlowNode for entry | ControlFlowNode for entry |
-| TarSlipImprov.py:130:5:130:7 | ControlFlowNode for tar | TarSlipImprov.py:129:6:129:26 | ControlFlowNode for Attribute() | TarSlipImprov.py:130:5:130:7 | ControlFlowNode for tar | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:129:6:129:26 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:130:5:130:7 | ControlFlowNode for tar | ControlFlowNode for tar |
-| TarSlipImprov.py:134:1:134:3 | ControlFlowNode for tar | TarSlipImprov.py:133:7:133:39 | ControlFlowNode for Attribute() | TarSlipImprov.py:134:1:134:3 | ControlFlowNode for tar | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:133:7:133:39 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:134:1:134:3 | ControlFlowNode for tar | ControlFlowNode for tar |
-| TarSlipImprov.py:143:36:143:40 | ControlFlowNode for entry | TarSlipImprov.py:141:6:141:29 | ControlFlowNode for Attribute() | TarSlipImprov.py:143:36:143:40 | ControlFlowNode for entry | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:141:6:141:29 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:143:36:143:40 | ControlFlowNode for entry | ControlFlowNode for entry |
-| TarSlipImprov.py:169:9:169:12 | ControlFlowNode for tarc | TarSlipImprov.py:151:22:151:49 | ControlFlowNode for Attribute() | TarSlipImprov.py:169:9:169:12 | ControlFlowNode for tarc | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:151:22:151:49 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:169:9:169:12 | ControlFlowNode for tarc | ControlFlowNode for tarc |
-| TarSlipImprov.py:169:9:169:12 | ControlFlowNode for tarc | TarSlipImprov.py:159:26:159:51 | ControlFlowNode for Attribute() | TarSlipImprov.py:169:9:169:12 | ControlFlowNode for tarc | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:159:26:159:51 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:169:9:169:12 | ControlFlowNode for tarc | ControlFlowNode for tarc |
-| TarSlipImprov.py:178:36:178:40 | ControlFlowNode for entry | TarSlipImprov.py:176:6:176:31 | ControlFlowNode for Attribute() | TarSlipImprov.py:178:36:178:40 | ControlFlowNode for entry | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:176:6:176:31 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:178:36:178:40 | ControlFlowNode for entry | ControlFlowNode for entry |
-| TarSlipImprov.py:184:21:184:25 | ControlFlowNode for entry | TarSlipImprov.py:182:6:182:31 | ControlFlowNode for Attribute() | TarSlipImprov.py:184:21:184:25 | ControlFlowNode for entry | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:182:6:182:31 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:184:21:184:25 | ControlFlowNode for entry | ControlFlowNode for entry |
-| TarSlipImprov.py:189:1:189:3 | ControlFlowNode for tar | TarSlipImprov.py:188:7:188:27 | ControlFlowNode for Attribute() | TarSlipImprov.py:189:1:189:3 | ControlFlowNode for tar | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:188:7:188:27 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:189:1:189:3 | ControlFlowNode for tar | ControlFlowNode for tar |
-| TarSlipImprov.py:194:49:194:51 | ControlFlowNode for tar | TarSlipImprov.py:193:6:193:31 | ControlFlowNode for Attribute() | TarSlipImprov.py:194:49:194:51 | ControlFlowNode for tar | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:193:6:193:31 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:194:49:194:51 | ControlFlowNode for tar | ControlFlowNode for tar |
-| TarSlipImprov.py:211:5:211:7 | ControlFlowNode for tar | TarSlipImprov.py:210:6:210:43 | ControlFlowNode for Attribute() | TarSlipImprov.py:211:5:211:7 | ControlFlowNode for tar | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:210:6:210:43 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:211:5:211:7 | ControlFlowNode for tar | ControlFlowNode for tar |
-| TarSlipImprov.py:236:44:236:50 | ControlFlowNode for members | TarSlipImprov.py:231:6:231:38 | ControlFlowNode for Attribute() | TarSlipImprov.py:236:44:236:50 | ControlFlowNode for members | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:231:6:231:38 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:236:44:236:50 | ControlFlowNode for members | ControlFlowNode for members |
-| TarSlipImprov.py:254:1:254:31 | ControlFlowNode for Attribute() | TarSlipImprov.py:254:1:254:31 | ControlFlowNode for Attribute() | TarSlipImprov.py:254:1:254:31 | ControlFlowNode for Attribute() | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:254:1:254:31 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:254:1:254:31 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() |
-| TarSlipImprov.py:261:25:261:29 | ControlFlowNode for entry | TarSlipImprov.py:258:6:258:26 | ControlFlowNode for Attribute() | TarSlipImprov.py:261:25:261:29 | ControlFlowNode for entry | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:258:6:258:26 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:261:25:261:29 | ControlFlowNode for entry | ControlFlowNode for entry |
-| TarSlipImprov.py:268:21:268:25 | ControlFlowNode for entry | TarSlipImprov.py:264:6:264:38 | ControlFlowNode for Attribute() | TarSlipImprov.py:268:21:268:25 | ControlFlowNode for entry | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:264:6:264:38 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:268:21:268:25 | ControlFlowNode for entry | ControlFlowNode for entry |
-| TarSlipImprov.py:274:25:274:29 | ControlFlowNode for entry | TarSlipImprov.py:271:6:271:39 | ControlFlowNode for Attribute() | TarSlipImprov.py:274:25:274:29 | ControlFlowNode for entry | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:271:6:271:39 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:274:25:274:29 | ControlFlowNode for entry | ControlFlowNode for entry |
-| TarSlipImprov.py:280:21:280:25 | ControlFlowNode for entry | TarSlipImprov.py:276:6:276:38 | ControlFlowNode for Attribute() | TarSlipImprov.py:280:21:280:25 | ControlFlowNode for entry | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:276:6:276:38 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:280:21:280:25 | ControlFlowNode for entry | ControlFlowNode for entry |
-| TarSlipImprov.py:284:5:284:7 | ControlFlowNode for tar | TarSlipImprov.py:283:6:283:51 | ControlFlowNode for Attribute() | TarSlipImprov.py:284:5:284:7 | ControlFlowNode for tar | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:283:6:283:51 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:284:5:284:7 | ControlFlowNode for tar | ControlFlowNode for tar |
-| TarSlipImprov.py:288:49:288:51 | ControlFlowNode for tar | TarSlipImprov.py:287:7:287:28 | ControlFlowNode for Attribute() | TarSlipImprov.py:288:49:288:51 | ControlFlowNode for tar | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:287:7:287:28 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:288:49:288:51 | ControlFlowNode for tar | ControlFlowNode for tar |
-| TarSlipImprov.py:293:1:293:3 | ControlFlowNode for tar | TarSlipImprov.py:292:7:292:39 | ControlFlowNode for Attribute() | TarSlipImprov.py:293:1:293:3 | ControlFlowNode for tar | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:292:7:292:39 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:293:1:293:3 | ControlFlowNode for tar | ControlFlowNode for tar |
-| TarSlipImprov.py:301:49:301:51 | ControlFlowNode for tar | TarSlipImprov.py:300:6:300:51 | ControlFlowNode for Attribute() | TarSlipImprov.py:301:49:301:51 | ControlFlowNode for tar | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:300:6:300:51 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:301:49:301:51 | ControlFlowNode for tar | ControlFlowNode for tar |
-| TarSlipImprov.py:310:49:310:54 | ControlFlowNode for result | TarSlipImprov.py:304:7:304:39 | ControlFlowNode for Attribute() | TarSlipImprov.py:310:49:310:54 | ControlFlowNode for result | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:304:7:304:39 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:310:49:310:54 | ControlFlowNode for result | ControlFlowNode for result |
-| TarSlipImprov.py:316:1:316:46 | ControlFlowNode for Attribute() | TarSlipImprov.py:316:1:316:46 | ControlFlowNode for Attribute() | TarSlipImprov.py:316:1:316:46 | ControlFlowNode for Attribute() | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:316:1:316:46 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:316:1:316:46 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() |
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/TarSlip.qlref b/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/TarSlip.qlref
index a518196b698..2842a87d080 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/TarSlip.qlref
+++ b/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/TarSlip.qlref
@@ -1 +1,2 @@
-experimental/Security/CWE-022bis/TarSlipImprov.ql
+query: experimental/Security/CWE-022bis/TarSlipImprov.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/TarSlipImprov.py b/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/TarSlipImprov.py
index 15bc66b4aea..3b59f24e402 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/TarSlipImprov.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/TarSlipImprov.py
@@ -12,14 +12,14 @@ import os.path
unsafe_filename_tar = sys.argv[2]
safe_filename_tar = "safe_path.tar"
-tar = tarfile.open(unsafe_filename_tar)
+tar = tarfile.open(unsafe_filename_tar) # $ Source[py/tarslip-extended]
result = []
for member in tar:
if ".." in member.name:
raise ValueError("Path in member name !!!")
result.append(member)
path = unsafe_filename_tar
-tar.extractall(path=path, members=result)
+tar.extractall(path=path, members=result) # $ Alert[py/tarslip-extended]
tar.close()
@@ -35,27 +35,27 @@ def members_filter1(tarfile):
result.append(member)
return result
-tar = tarfile.open(unsafe_filename_tar)
-tar.extractall(path=tempfile.mkdtemp(), members=members_filter1(tar))
+tar = tarfile.open(unsafe_filename_tar) # $ Source[py/tarslip-extended]
+tar.extractall(path=tempfile.mkdtemp(), members=members_filter1(tar)) # $ Alert[py/tarslip-extended]
tar.close()
-with tarfile.open(unsafe_filename_tar) as tar:
+with tarfile.open(unsafe_filename_tar) as tar: # $ Source[py/tarslip-extended]
for entry in tar:
if ".." in entry.name:
raise ValueError("Illegal tar archive entry")
- tar.extract(entry, "/tmp/unpack/")
+ tar.extract(entry, "/tmp/unpack/") # $ Alert[py/tarslip-extended]
def _validate_archive_name(name, target):
if not os.path.abspath(os.path.join(target, name)).startswith(target + os.path.sep):
raise ValueError(f"Provided language pack contains invalid name {name}")
-with tarfile.open(unsafe_filename_tar) as tar:
+with tarfile.open(unsafe_filename_tar) as tar: # $ Source[py/tarslip-extended]
target = "/tmp/unpack"
for entry in tar:
_validate_archive_name(entry.name, target)
- tar.extract(entry, target)
+ tar.extract(entry, target) # $ Alert[py/tarslip-extended]
def members_filter2(tarfile):
@@ -85,10 +85,10 @@ def _validate_archive_name(name, target):
raise ValueError(f"Provided language pack contains invalid name {name}")
target = "/tmp/unpack"
-with tarfile.open(unsafe_filename_tar, "r") as tar:
+with tarfile.open(unsafe_filename_tar, "r") as tar: # $ Source[py/tarslip-extended]
for info in tar.getmembers():
_validate_tar_info(info, target)
- tar.extractall(target)
+ tar.extractall(target) # $ Alert[py/tarslip-extended]
def members_filter3(tarfile):
@@ -108,11 +108,11 @@ tar.extractall(path=tempfile.mkdtemp(), members=members_filter3(tar))
tar.close()
-tar = tarfile.open(unsafe_filename_tar)
+tar = tarfile.open(unsafe_filename_tar) # $ Source[py/tarslip-extended]
tarf = tar.getmembers()
for f in tarf:
if not f.issym():
- tar.extractall(path=tempfile.mkdtemp(), members=[f])
+ tar.extractall(path=tempfile.mkdtemp(), members=[f]) # $ Alert[py/tarslip-extended]
tar.close()
@@ -120,27 +120,27 @@ class MKTar(TarFile):
pass
tarball = unsafe_filename_tar
-with MKTar.open(name=tarball) as tar:
+with MKTar.open(name=tarball) as tar: # $ Source[py/tarslip-extended]
for entry in tar:
- tar._extract_member(entry, entry.name)
+ tar._extract_member(entry, entry.name) # $ Alert[py/tarslip-extended]
tarball = unsafe_filename_tar
-with tarfile.open(tarball) as tar:
- tar.extractall()
+with tarfile.open(tarball) as tar: # $ Source[py/tarslip-extended]
+ tar.extractall() # $ Alert[py/tarslip-extended]
-tar = tarfile.open(unsafe_filename_tar)
-tar.extractall(path=tempfile.mkdtemp(), members=None)
+tar = tarfile.open(unsafe_filename_tar) # $ Source[py/tarslip-extended]
+tar.extractall(path=tempfile.mkdtemp(), members=None) # $ Alert[py/tarslip-extended]
class MKTar(tarfile.TarFile):
pass
tarball = unsafe_filename_tar
-with MKTar.open(name=tarball) as tar:
+with MKTar.open(name=tarball) as tar: # $ Source[py/tarslip-extended]
for entry in tar:
- tar._extract_member(entry, entry.name)
+ tar._extract_member(entry, entry.name) # $ Alert[py/tarslip-extended]
@contextmanager
@@ -148,7 +148,7 @@ def py2_tarxz(filename):
with tempfile.TemporaryFile() as tmp:
subprocess.check_call(["xz", "-dc", filename], stdout=tmp.fileno())
tmp.seek(0)
- with closing(tarfile.TarFile(fileobj=tmp)) as tf:
+ with closing(tarfile.TarFile(fileobj=tmp)) as tf: # $ Source[py/tarslip-extended]
yield tf
def unpack_tarball(tar_filename, dest):
@@ -156,7 +156,7 @@ def unpack_tarball(tar_filename, dest):
# Py 2.7 lacks lzma support
tar_cm = py2_tarxz(tar_filename)
else:
- tar_cm = closing(tarfile.open(tar_filename))
+ tar_cm = closing(tarfile.open(tar_filename)) # $ Source[py/tarslip-extended]
base_dir = None
with tar_cm as tarc:
@@ -166,32 +166,32 @@ def unpack_tarball(tar_filename, dest):
base_dir = base_name
elif base_dir != base_name:
print('Unexpected path in %s: %s' % (tar_filename, base_name))
- tarc.extractall(dest)
+ tarc.extractall(dest) # $ Alert[py/tarslip-extended]
return os.path.join(dest, base_dir)
unpack_tarball(unsafe_filename_tar, "/tmp/unpack")
tarball = unsafe_filename_tar
-with tarfile.open(name=tarball) as tar:
+with tarfile.open(name=tarball) as tar: # $ Source[py/tarslip-extended]
for entry in tar:
- tar._extract_member(entry, entry.name)
+ tar._extract_member(entry, entry.name) # $ Alert[py/tarslip-extended]
tarball = unsafe_filename_tar
-with tarfile.open(name=tarball) as tar:
+with tarfile.open(name=tarball) as tar: # $ Source[py/tarslip-extended]
for entry in tar:
- tar.extract(entry, "/tmp/unpack/")
+ tar.extract(entry, "/tmp/unpack/") # $ Alert[py/tarslip-extended]
tarball = unsafe_filename_tar
-tar = tarfile.open(tarball)
-tar.extractall("/tmp/unpack/")
+tar = tarfile.open(tarball) # $ Source[py/tarslip-extended]
+tar.extractall("/tmp/unpack/") # $ Alert[py/tarslip-extended]
tarball = unsafe_filename_tar
-with tarfile.open(tarball, "r") as tar:
- tar.extractall(path="/tmp/unpack/", members=tar)
+with tarfile.open(tarball, "r") as tar: # $ Source[py/tarslip-extended]
+ tar.extractall(path="/tmp/unpack/", members=tar) # $ Alert[py/tarslip-extended]
def members_filter4(tarfile):
@@ -207,8 +207,8 @@ tar.extractall(path=tempfile.mkdtemp(), members=members_filter4(tar))
tar.close()
-with tarfile.open(unsafe_filename_tar, "r") as tar:
- tar.extractall(path="/tmp/unpack")
+with tarfile.open(unsafe_filename_tar, "r") as tar: # $ Source[py/tarslip-extended]
+ tar.extractall(path="/tmp/unpack") # $ Alert[py/tarslip-extended]
def members_filter5(tarfile):
@@ -228,12 +228,12 @@ filename = unsafe_filename_tar
tmp_dir = "/tmp/"
read_type = "r:gz" if filename.endswith("tgz") else "r"
-with tarfile.open(filename, read_type) as corpus_tar:
+with tarfile.open(filename, read_type) as corpus_tar: # $ Source[py/tarslip-extended]
members = []
for f in corpus_tar:
if not os.path.isfile(os.path.join(tmp_dir, f.name)):
members.append(f)
- corpus_tar.extractall(tmp_dir, members=members)
+ corpus_tar.extractall(tmp_dir, members=members) # $ Alert[py/tarslip-extended]
def members_filter6(tarfile):
@@ -251,66 +251,66 @@ tar.close()
archive_path = unsafe_filename_tar
target_dir = "/tmp/unpack"
-tarfile.open(archive_path, "r").extractall(path=target_dir)
+tarfile.open(archive_path, "r").extractall(path=target_dir) # $ Alert[py/tarslip-extended]
tarball = unsafe_filename_tar
-with tarfile.open(tarball) as tar:
+with tarfile.open(tarball) as tar: # $ Source[py/tarslip-extended]
for entry in tar:
if entry.isfile():
- tar.extract(entry, "/tmp/unpack/")
+ tar.extract(entry, "/tmp/unpack/") # $ Alert[py/tarslip-extended]
-with tarfile.open(unsafe_filename_tar) as tar:
+with tarfile.open(unsafe_filename_tar) as tar: # $ Source[py/tarslip-extended]
for entry in tar:
if entry.name.startswith("/"):
raise ValueError("Illegal tar archive entry")
- tar.extract(entry, "/tmp/unpack/")
+ tar.extract(entry, "/tmp/unpack/") # $ Alert[py/tarslip-extended]
tarball = unsafe_filename_tar
-with tarfile.TarFile(tarball, mode="r") as tar:
+with tarfile.TarFile(tarball, mode="r") as tar: # $ Source[py/tarslip-extended]
for entry in tar:
if entry.isfile():
- tar.extract(entry, "/tmp/unpack/")
+ tar.extract(entry, "/tmp/unpack/") # $ Alert[py/tarslip-extended]
-with tarfile.open(unsafe_filename_tar) as tar:
+with tarfile.open(unsafe_filename_tar) as tar: # $ Source[py/tarslip-extended]
for entry in tar:
if os.path.isabs(entry.name):
raise ValueError("Illegal tar archive entry")
- tar.extract(entry, "/tmp/unpack/")
+ tar.extract(entry, "/tmp/unpack/") # $ Alert[py/tarslip-extended]
-with tarfile.TarFile(unsafe_filename_tar, mode="r") as tar:
- tar.extractall(path="/tmp/unpack")
+with tarfile.TarFile(unsafe_filename_tar, mode="r") as tar: # $ Source[py/tarslip-extended]
+ tar.extractall(path="/tmp/unpack") # $ Alert[py/tarslip-extended]
-tar = tarfile.open(filename)
-tar.extractall(path=tempfile.mkdtemp(), members=tar.getmembers())
+tar = tarfile.open(filename) # $ Source[py/tarslip-extended]
+tar.extractall(path=tempfile.mkdtemp(), members=tar.getmembers()) # $ Alert[py/tarslip-extended]
tar.close()
-tar = tarfile.open(unsafe_filename_tar)
-tar.extractall(path=tempfile.mkdtemp(), members=None)
+tar = tarfile.open(unsafe_filename_tar) # $ Source[py/tarslip-extended]
+tar.extractall(path=tempfile.mkdtemp(), members=None) # $ Alert[py/tarslip-extended]
tar.extractall(path=tempfile.mkdtemp(), members=members_filter4(tar))
tar.close()
-with tarfile.TarFile(unsafe_filename_tar, mode="r") as tar:
- tar.extractall(path="/tmp/unpack/", members=tar)
+with tarfile.TarFile(unsafe_filename_tar, mode="r") as tar: # $ Source[py/tarslip-extended]
+ tar.extractall(path="/tmp/unpack/", members=tar) # $ Alert[py/tarslip-extended]
-tar = tarfile.open(unsafe_filename_tar)
+tar = tarfile.open(unsafe_filename_tar) # $ Source[py/tarslip-extended]
result = []
for member in tar:
if member.issym():
raise ValueError("But it is a symlink")
result.append(member)
-tar.extractall(path=tempfile.mkdtemp(), members=result)
+tar.extractall(path=tempfile.mkdtemp(), members=result) # $ Alert[py/tarslip-extended]
tar.close()
archive_path = unsafe_filename_tar
target_dir = "/tmp/unpack"
-tarfile.TarFile(unsafe_filename_tar, mode="r").extractall(path=target_dir)
\ No newline at end of file
+tarfile.TarFile(unsafe_filename_tar, mode="r").extractall(path=target_dir) # $ Alert[py/tarslip-extended]
\ No newline at end of file
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/ZipSlip.expected b/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/ZipSlip.expected
index 6b618335d81..eecdfd0494f 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/ZipSlip.expected
+++ b/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/ZipSlip.expected
@@ -1,3 +1,9 @@
+#select
+| zipslip_bad.py:8:10:8:31 | ControlFlowNode for Attribute() | zipslip_bad.py:8:10:8:31 | ControlFlowNode for Attribute() | zipslip_bad.py:11:25:11:29 | ControlFlowNode for entry | This unsanitized archive entry, which may contain '..', is used in a $@. | zipslip_bad.py:11:25:11:29 | ControlFlowNode for entry | file system operation |
+| zipslip_bad.py:14:10:14:28 | ControlFlowNode for Attribute() | zipslip_bad.py:14:10:14:28 | ControlFlowNode for Attribute() | zipslip_bad.py:17:26:17:30 | ControlFlowNode for entry | This unsanitized archive entry, which may contain '..', is used in a $@. | zipslip_bad.py:17:26:17:30 | ControlFlowNode for entry | file system operation |
+| zipslip_bad.py:20:10:20:27 | ControlFlowNode for Attribute() | zipslip_bad.py:20:10:20:27 | ControlFlowNode for Attribute() | zipslip_bad.py:23:29:23:33 | ControlFlowNode for entry | This unsanitized archive entry, which may contain '..', is used in a $@. | zipslip_bad.py:23:29:23:33 | ControlFlowNode for entry | file system operation |
+| zipslip_bad.py:27:10:27:22 | ControlFlowNode for Attribute() | zipslip_bad.py:27:10:27:22 | ControlFlowNode for Attribute() | zipslip_bad.py:30:25:30:25 | ControlFlowNode for x | This unsanitized archive entry, which may contain '..', is used in a $@. | zipslip_bad.py:30:25:30:25 | ControlFlowNode for x | file system operation |
+| zipslip_bad.py:34:16:34:28 | ControlFlowNode for Attribute() | zipslip_bad.py:34:16:34:28 | ControlFlowNode for Attribute() | zipslip_bad.py:37:32:37:32 | ControlFlowNode for x | This unsanitized archive entry, which may contain '..', is used in a $@. | zipslip_bad.py:37:32:37:32 | ControlFlowNode for x | file system operation |
edges
| zipslip_bad.py:8:10:8:31 | ControlFlowNode for Attribute() | zipslip_bad.py:8:36:8:39 | ControlFlowNode for zipf | provenance | |
| zipslip_bad.py:8:36:8:39 | ControlFlowNode for zipf | zipslip_bad.py:10:13:10:17 | ControlFlowNode for entry | provenance | |
@@ -36,9 +42,3 @@ nodes
| zipslip_bad.py:35:9:35:9 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| zipslip_bad.py:37:32:37:32 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
subpaths
-#select
-| zipslip_bad.py:8:10:8:31 | ControlFlowNode for Attribute() | zipslip_bad.py:8:10:8:31 | ControlFlowNode for Attribute() | zipslip_bad.py:11:25:11:29 | ControlFlowNode for entry | This unsanitized archive entry, which may contain '..', is used in a $@. | zipslip_bad.py:11:25:11:29 | ControlFlowNode for entry | file system operation |
-| zipslip_bad.py:14:10:14:28 | ControlFlowNode for Attribute() | zipslip_bad.py:14:10:14:28 | ControlFlowNode for Attribute() | zipslip_bad.py:17:26:17:30 | ControlFlowNode for entry | This unsanitized archive entry, which may contain '..', is used in a $@. | zipslip_bad.py:17:26:17:30 | ControlFlowNode for entry | file system operation |
-| zipslip_bad.py:20:10:20:27 | ControlFlowNode for Attribute() | zipslip_bad.py:20:10:20:27 | ControlFlowNode for Attribute() | zipslip_bad.py:23:29:23:33 | ControlFlowNode for entry | This unsanitized archive entry, which may contain '..', is used in a $@. | zipslip_bad.py:23:29:23:33 | ControlFlowNode for entry | file system operation |
-| zipslip_bad.py:27:10:27:22 | ControlFlowNode for Attribute() | zipslip_bad.py:27:10:27:22 | ControlFlowNode for Attribute() | zipslip_bad.py:30:25:30:25 | ControlFlowNode for x | This unsanitized archive entry, which may contain '..', is used in a $@. | zipslip_bad.py:30:25:30:25 | ControlFlowNode for x | file system operation |
-| zipslip_bad.py:34:16:34:28 | ControlFlowNode for Attribute() | zipslip_bad.py:34:16:34:28 | ControlFlowNode for Attribute() | zipslip_bad.py:37:32:37:32 | ControlFlowNode for x | This unsanitized archive entry, which may contain '..', is used in a $@. | zipslip_bad.py:37:32:37:32 | ControlFlowNode for x | file system operation |
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/ZipSlip.qlref b/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/ZipSlip.qlref
index 717dc9d0f10..177a74d6bd7 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/ZipSlip.qlref
+++ b/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/ZipSlip.qlref
@@ -1 +1,2 @@
-experimental/Security/CWE-022/ZipSlip.ql
+query: experimental/Security/CWE-022/ZipSlip.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/zipslip_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/zipslip_bad.py
index c622ead874c..4e7195cf856 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/zipslip_bad.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/zipslip_bad.py
@@ -5,35 +5,35 @@ import gzip
import zipfile
def unzip(filename):
- with tarfile.open(filename) as zipf:
+ with tarfile.open(filename) as zipf: # $ Alert[py/zipslip]
#BAD : This could write any file on the filesystem.
for entry in zipf:
- shutil.move(entry, "/tmp/unpack/")
+ shutil.move(entry, "/tmp/unpack/") # $ Sink[py/zipslip]
def unzip1(filename):
- with gzip.open(filename) as zipf:
+ with gzip.open(filename) as zipf: # $ Alert[py/zipslip]
#BAD : This could write any file on the filesystem.
for entry in zipf:
- shutil.copy2(entry, "/tmp/unpack/")
+ shutil.copy2(entry, "/tmp/unpack/") # $ Sink[py/zipslip]
def unzip2(filename):
- with bz2.open(filename) as zipf:
+ with bz2.open(filename) as zipf: # $ Alert[py/zipslip]
#BAD : This could write any file on the filesystem.
for entry in zipf:
- shutil.copyfile(entry, "/tmp/unpack/")
+ shutil.copyfile(entry, "/tmp/unpack/") # $ Sink[py/zipslip]
def unzip3(filename):
zf = zipfile.ZipFile(filename)
- with zf.namelist() as filelist:
+ with zf.namelist() as filelist: # $ Alert[py/zipslip]
#BAD : This could write any file on the filesystem.
for x in filelist:
- shutil.copy(x, "/tmp/unpack/")
+ shutil.copy(x, "/tmp/unpack/") # $ Sink[py/zipslip]
def unzip4(filename):
zf = zipfile.ZipFile(filename)
- filelist = zf.namelist()
+ filelist = zf.namelist() # $ Alert[py/zipslip]
for x in filelist:
with zf.open(x) as srcf:
- shutil.copyfileobj(x, "/tmp/unpack/")
+ shutil.copyfileobj(x, "/tmp/unpack/") # $ Sink[py/zipslip]
import tty # to set the import root so we can identify the standard library
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-074-RemoteCommandExecution/RemoteCommandExecution.qlref b/python/ql/test/experimental/query-tests/Security/CWE-074-RemoteCommandExecution/RemoteCommandExecution.qlref
index dc5c7028f32..96e8c4e0d44 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-074-RemoteCommandExecution/RemoteCommandExecution.qlref
+++ b/python/ql/test/experimental/query-tests/Security/CWE-074-RemoteCommandExecution/RemoteCommandExecution.qlref
@@ -1 +1 @@
-experimental/Security/CWE-074/remoteCommandExecution/RemoteCommandExecution.ql
\ No newline at end of file
+query: experimental/Security/CWE-074/remoteCommandExecution/RemoteCommandExecution.ql
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-079/EmailXss.expected b/python/ql/test/experimental/query-tests/Security/CWE-079/EmailXss.expected
index 8f0493b7927..0a7dde1b81d 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-079/EmailXss.expected
+++ b/python/ql/test/experimental/query-tests/Security/CWE-079/EmailXss.expected
@@ -1,3 +1,18 @@
+#select
+| django_mail.py:14:48:14:82 | ControlFlowNode for Attribute() | django_mail.py:14:48:14:82 | ControlFlowNode for Attribute() | django_mail.py:14:48:14:82 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | django_mail.py:14:48:14:82 | ControlFlowNode for Attribute() | a user-provided value |
+| django_mail.py:23:30:23:64 | ControlFlowNode for Attribute() | django_mail.py:23:30:23:64 | ControlFlowNode for Attribute() | django_mail.py:23:30:23:64 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | django_mail.py:23:30:23:64 | ControlFlowNode for Attribute() | a user-provided value |
+| django_mail.py:25:32:25:66 | ControlFlowNode for Attribute() | django_mail.py:25:32:25:66 | ControlFlowNode for Attribute() | django_mail.py:25:32:25:66 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | django_mail.py:25:32:25:66 | ControlFlowNode for Attribute() | a user-provided value |
+| flask_mail.py:13:22:13:41 | ControlFlowNode for Subscript | flask_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | flask_mail.py:13:22:13:41 | ControlFlowNode for Subscript | Cross-site scripting vulnerability due to $@. | flask_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value |
+| flask_mail.py:18:14:18:33 | ControlFlowNode for Subscript | flask_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | flask_mail.py:18:14:18:33 | ControlFlowNode for Subscript | Cross-site scripting vulnerability due to $@. | flask_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value |
+| flask_mail.py:31:24:31:43 | ControlFlowNode for Subscript | flask_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | flask_mail.py:31:24:31:43 | ControlFlowNode for Subscript | Cross-site scripting vulnerability due to $@. | flask_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value |
+| sendgrid_mail.py:14:22:14:49 | ControlFlowNode for Subscript | sendgrid_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | sendgrid_mail.py:14:22:14:49 | ControlFlowNode for Subscript | Cross-site scripting vulnerability due to $@. | sendgrid_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value |
+| sendgrid_mail.py:26:22:26:62 | ControlFlowNode for HtmlContent() | sendgrid_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | sendgrid_mail.py:26:22:26:62 | ControlFlowNode for HtmlContent() | Cross-site scripting vulnerability due to $@. | sendgrid_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value |
+| sendgrid_mail.py:37:41:37:68 | ControlFlowNode for Subscript | sendgrid_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | sendgrid_mail.py:37:41:37:68 | ControlFlowNode for Subscript | Cross-site scripting vulnerability due to $@. | sendgrid_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value |
+| sendgrid_via_mail_send_post_request_body_bad.py:16:26:16:79 | ControlFlowNode for Attribute() | sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | ControlFlowNode for ImportMember | sendgrid_via_mail_send_post_request_body_bad.py:16:26:16:79 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | ControlFlowNode for ImportMember | a user-provided value |
+| sendgrid_via_mail_send_post_request_body_bad.py:27:25:27:77 | ControlFlowNode for Attribute() | sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | ControlFlowNode for ImportMember | sendgrid_via_mail_send_post_request_body_bad.py:27:25:27:77 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | ControlFlowNode for ImportMember | a user-provided value |
+| sendgrid_via_mail_send_post_request_body_bad.py:41:25:41:79 | ControlFlowNode for Attribute() | sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | ControlFlowNode for ImportMember | sendgrid_via_mail_send_post_request_body_bad.py:41:25:41:79 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | ControlFlowNode for ImportMember | a user-provided value |
+| smtplib_bad_subparts.py:24:22:24:25 | ControlFlowNode for html | smtplib_bad_subparts.py:2:26:2:32 | ControlFlowNode for ImportMember | smtplib_bad_subparts.py:24:22:24:25 | ControlFlowNode for html | Cross-site scripting vulnerability due to $@. | smtplib_bad_subparts.py:2:26:2:32 | ControlFlowNode for ImportMember | a user-provided value |
+| smtplib_bad_via_attach.py:27:22:27:25 | ControlFlowNode for html | smtplib_bad_via_attach.py:2:26:2:32 | ControlFlowNode for ImportMember | smtplib_bad_via_attach.py:27:22:27:25 | ControlFlowNode for html | Cross-site scripting vulnerability due to $@. | smtplib_bad_via_attach.py:2:26:2:32 | ControlFlowNode for ImportMember | a user-provided value |
edges
| flask_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | flask_mail.py:1:19:1:25 | ControlFlowNode for request | provenance | |
| flask_mail.py:1:19:1:25 | ControlFlowNode for request | flask_mail.py:13:22:13:28 | ControlFlowNode for request | provenance | |
@@ -77,18 +92,3 @@ nodes
| smtplib_bad_via_attach.py:23:5:23:8 | ControlFlowNode for html | semmle.label | ControlFlowNode for html |
| smtplib_bad_via_attach.py:27:22:27:25 | ControlFlowNode for html | semmle.label | ControlFlowNode for html |
subpaths
-#select
-| django_mail.py:14:48:14:82 | ControlFlowNode for Attribute() | django_mail.py:14:48:14:82 | ControlFlowNode for Attribute() | django_mail.py:14:48:14:82 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | django_mail.py:14:48:14:82 | ControlFlowNode for Attribute() | a user-provided value |
-| django_mail.py:23:30:23:64 | ControlFlowNode for Attribute() | django_mail.py:23:30:23:64 | ControlFlowNode for Attribute() | django_mail.py:23:30:23:64 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | django_mail.py:23:30:23:64 | ControlFlowNode for Attribute() | a user-provided value |
-| django_mail.py:25:32:25:66 | ControlFlowNode for Attribute() | django_mail.py:25:32:25:66 | ControlFlowNode for Attribute() | django_mail.py:25:32:25:66 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | django_mail.py:25:32:25:66 | ControlFlowNode for Attribute() | a user-provided value |
-| flask_mail.py:13:22:13:41 | ControlFlowNode for Subscript | flask_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | flask_mail.py:13:22:13:41 | ControlFlowNode for Subscript | Cross-site scripting vulnerability due to $@. | flask_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value |
-| flask_mail.py:18:14:18:33 | ControlFlowNode for Subscript | flask_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | flask_mail.py:18:14:18:33 | ControlFlowNode for Subscript | Cross-site scripting vulnerability due to $@. | flask_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value |
-| flask_mail.py:31:24:31:43 | ControlFlowNode for Subscript | flask_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | flask_mail.py:31:24:31:43 | ControlFlowNode for Subscript | Cross-site scripting vulnerability due to $@. | flask_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value |
-| sendgrid_mail.py:14:22:14:49 | ControlFlowNode for Subscript | sendgrid_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | sendgrid_mail.py:14:22:14:49 | ControlFlowNode for Subscript | Cross-site scripting vulnerability due to $@. | sendgrid_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value |
-| sendgrid_mail.py:26:22:26:62 | ControlFlowNode for HtmlContent() | sendgrid_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | sendgrid_mail.py:26:22:26:62 | ControlFlowNode for HtmlContent() | Cross-site scripting vulnerability due to $@. | sendgrid_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value |
-| sendgrid_mail.py:37:41:37:68 | ControlFlowNode for Subscript | sendgrid_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | sendgrid_mail.py:37:41:37:68 | ControlFlowNode for Subscript | Cross-site scripting vulnerability due to $@. | sendgrid_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value |
-| sendgrid_via_mail_send_post_request_body_bad.py:16:26:16:79 | ControlFlowNode for Attribute() | sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | ControlFlowNode for ImportMember | sendgrid_via_mail_send_post_request_body_bad.py:16:26:16:79 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | ControlFlowNode for ImportMember | a user-provided value |
-| sendgrid_via_mail_send_post_request_body_bad.py:27:25:27:77 | ControlFlowNode for Attribute() | sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | ControlFlowNode for ImportMember | sendgrid_via_mail_send_post_request_body_bad.py:27:25:27:77 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | ControlFlowNode for ImportMember | a user-provided value |
-| sendgrid_via_mail_send_post_request_body_bad.py:41:25:41:79 | ControlFlowNode for Attribute() | sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | ControlFlowNode for ImportMember | sendgrid_via_mail_send_post_request_body_bad.py:41:25:41:79 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | ControlFlowNode for ImportMember | a user-provided value |
-| smtplib_bad_subparts.py:24:22:24:25 | ControlFlowNode for html | smtplib_bad_subparts.py:2:26:2:32 | ControlFlowNode for ImportMember | smtplib_bad_subparts.py:24:22:24:25 | ControlFlowNode for html | Cross-site scripting vulnerability due to $@. | smtplib_bad_subparts.py:2:26:2:32 | ControlFlowNode for ImportMember | a user-provided value |
-| smtplib_bad_via_attach.py:27:22:27:25 | ControlFlowNode for html | smtplib_bad_via_attach.py:2:26:2:32 | ControlFlowNode for ImportMember | smtplib_bad_via_attach.py:27:22:27:25 | ControlFlowNode for html | Cross-site scripting vulnerability due to $@. | smtplib_bad_via_attach.py:2:26:2:32 | ControlFlowNode for ImportMember | a user-provided value |
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-079/EmailXss.qlref b/python/ql/test/experimental/query-tests/Security/CWE-079/EmailXss.qlref
index fcc132dd66c..c141aa6746b 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-079/EmailXss.qlref
+++ b/python/ql/test/experimental/query-tests/Security/CWE-079/EmailXss.qlref
@@ -1 +1,2 @@
-experimental/Security/CWE-079/EmailXss.ql
+query: experimental/Security/CWE-079/EmailXss.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-079/django_mail.py b/python/ql/test/experimental/query-tests/Security/CWE-079/django_mail.py
index 178e8decc79..fb42c22f02e 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-079/django_mail.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-079/django_mail.py
@@ -11,7 +11,7 @@ def django_response(request):
https://github.com/django/django/blob/ca9872905559026af82000e46cde6f7dedc897b6/django/core/mail/__init__.py#L64
"""
send_mail("Subject", "plain-text body", "from@example.com",
- ["to@example.com"], html_message=django.http.request.GET.get("html"))
+ ["to@example.com"], html_message=django.http.request.GET.get("html")) # $ Alert
def django_response(request):
@@ -20,6 +20,6 @@ def django_response(request):
https://github.com/django/django/blob/ca9872905559026af82000e46cde6f7dedc897b6/django/core/mail/__init__.py#L90-L121
"""
mail_admins("Subject", "plain-text body",
- html_message=django.http.request.GET.get("html"))
+ html_message=django.http.request.GET.get("html")) # $ Alert
mail_managers("Subject", "plain-text body",
- html_message=django.http.request.GET.get("html"))
+ html_message=django.http.request.GET.get("html")) # $ Alert
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-079/flask_mail.py b/python/ql/test/experimental/query-tests/Security/CWE-079/flask_mail.py
index e8bdcc93634..6978ad741f6 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-079/flask_mail.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-079/flask_mail.py
@@ -1,4 +1,4 @@
-from flask import request, Flask
+from flask import request, Flask # $ Source
from flask_mail import Mail, Message
app = Flask(__name__)
@@ -10,12 +10,12 @@ def send():
sender="from@example.com",
recipients=["to@example.com"],
body="plain-text body",
- html=request.args["html"])
+ html=request.args["html"]) # $ Alert
# The message can contain a body and/or HTML:
msg.body = "plain-text body"
# The email's HTML can be set via msg.html or as an initialize argument when creating a Message object.
- msg.html = request.args["html"]
+ msg.html = request.args["html"] # $ Alert
mail.send(msg)
@@ -28,5 +28,5 @@ def connect():
msg = Message(subject="Subject",
sender="from@example.com",
recipients=["to@example.com"],
- html=request.args["html"])
+ html=request.args["html"]) # $ Alert
conn.send(msg)
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-079/sendgrid_mail.py b/python/ql/test/experimental/query-tests/Security/CWE-079/sendgrid_mail.py
index e10e8a030a8..4d89056f3fe 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-079/sendgrid_mail.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-079/sendgrid_mail.py
@@ -1,4 +1,4 @@
-from flask import request, Flask
+from flask import request, Flask # $ Source
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail, Email, To, Content, MimeType, HtmlContent
@@ -11,7 +11,7 @@ def send():
from_email='from_email@example.com',
to_emails='to@example.com',
subject='Sending with Twilio SendGrid is Fun',
- html_content=request.args["html_content"])
+ html_content=request.args["html_content"]) # $ Alert
sg = SendGridAPIClient('SENDGRID_API_KEY')
sg.send(message)
@@ -23,7 +23,7 @@ def send():
from_email='from_email@example.com',
to_emails='to@example.com',
subject='Sending with Twilio SendGrid is Fun',
- html_content=HtmlContent(request.args["html_content"]))
+ html_content=HtmlContent(request.args["html_content"])) # $ Alert
sg = SendGridAPIClient('SENDGRID_API_KEY')
sg.send(message)
@@ -34,7 +34,7 @@ def send_post():
from_email = Email("test@example.com")
to_email = To("test@example.com")
subject = "Sending with SendGrid is Fun"
- html_content = Content("text/html", request.args["html_content"])
+ html_content = Content("text/html", request.args["html_content"]) # $ Alert
plain_content = Content("text/plain", request.args["plain_content"])
mail = Mail(from_email, to_email, subject, plain_content, html_content)
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-079/sendgrid_via_mail_send_post_request_body_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-079/sendgrid_via_mail_send_post_request_body_bad.py
index fca641057da..30a67213b48 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-079/sendgrid_via_mail_send_post_request_body_bad.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-079/sendgrid_via_mail_send_post_request_body_bad.py
@@ -1,6 +1,6 @@
import sendgrid
import os
-from flask import request, Flask
+from flask import request, Flask # $ Source
app = Flask(__name__)
@@ -13,7 +13,7 @@ def send():
"content": [
{
"type": "text/html",
- "value": "{}".format(request.args["html_content"])
+ "value": "{}".format(request.args["html_content"]) # $ Alert
}
],
"from": {
@@ -24,7 +24,7 @@ def send():
"mail_settings": {
"footer": {
"enable": True,
- "html": "{}".format(request.args["html_footer"]),
+ "html": "{}".format(request.args["html_footer"]), # $ Alert
"text": "Thanks,/n The SendGrid Team"
},
},
@@ -38,7 +38,7 @@ def send():
"tracking_settings": {
"subscription_tracking": {
"enable": True,
- "html": "{}".format(request.args["html_tracking"]),
+ "html": "{}".format(request.args["html_tracking"]), # $ Alert
"substitution_tag": "<%click here%>",
"text": "If you would like to unsubscribe and stop receiving these emails <% click here %>."
}
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-079/smtplib_bad_subparts.py b/python/ql/test/experimental/query-tests/Security/CWE-079/smtplib_bad_subparts.py
index 209bd889393..20c8e3466ae 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-079/smtplib_bad_subparts.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-079/smtplib_bad_subparts.py
@@ -1,5 +1,5 @@
# This test checks that the developer doesn't pass a MIMEText instance to a MIMEMultipart initializer via the subparts parameter.
-from flask import Flask, request
+from flask import Flask, request # $ Source
import json
import smtplib
import ssl
@@ -21,7 +21,7 @@ def email_person():
# Turn these into plain/html MIMEText objects
part1 = MIMEText(text, "plain")
- part2 = MIMEText(html, "html")
+ part2 = MIMEText(html, "html") # $ Alert
message = MIMEMultipart(_subparts=(part1, part2))
message["Subject"] = "multipart test"
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-079/smtplib_bad_via_attach.py b/python/ql/test/experimental/query-tests/Security/CWE-079/smtplib_bad_via_attach.py
index 48a228b0bc6..d50ab028087 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-079/smtplib_bad_via_attach.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-079/smtplib_bad_via_attach.py
@@ -1,5 +1,5 @@
# This test checks that the developer doesn't pass a MIMEText instance to a MIMEMultipart message.
-from flask import Flask, request
+from flask import Flask, request # $ Source
import json
import smtplib, ssl
from email.mime.text import MIMEText
@@ -24,7 +24,7 @@ def email_person():
# Turn these into plain/html MIMEText objects
part1 = MIMEText(text, "plain")
- part2 = MIMEText(html, "html")
+ part2 = MIMEText(html, "html") # $ Alert
# Add HTML/plain-text parts to MIMEMultipart message
# The email client will try to render the last part first
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-091-XsltInjection/XsltInjection.expected b/python/ql/test/experimental/query-tests/Security/CWE-091-XsltInjection/XsltInjection.expected
index 8d960a22dfd..28c85388a97 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-091-XsltInjection/XsltInjection.expected
+++ b/python/ql/test/experimental/query-tests/Security/CWE-091-XsltInjection/XsltInjection.expected
@@ -1,3 +1,10 @@
+#select
+| xslt.py:14:29:14:37 | ControlFlowNode for xslt_root | xslt.py:3:26:3:32 | ControlFlowNode for ImportMember | xslt.py:14:29:14:37 | ControlFlowNode for xslt_root | This XSLT query depends on $@. | xslt.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value |
+| xsltInjection.py:12:28:12:36 | ControlFlowNode for xslt_root | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | xsltInjection.py:12:28:12:36 | ControlFlowNode for xslt_root | This XSLT query depends on $@. | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value |
+| xsltInjection.py:21:29:21:37 | ControlFlowNode for xslt_root | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | xsltInjection.py:21:29:21:37 | ControlFlowNode for xslt_root | This XSLT query depends on $@. | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value |
+| xsltInjection.py:31:24:31:32 | ControlFlowNode for xslt_root | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | xsltInjection.py:31:24:31:32 | ControlFlowNode for xslt_root | This XSLT query depends on $@. | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value |
+| xsltInjection.py:40:24:40:32 | ControlFlowNode for xslt_root | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | xsltInjection.py:40:24:40:32 | ControlFlowNode for xslt_root | This XSLT query depends on $@. | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value |
+| xsltInjection.py:50:24:50:32 | ControlFlowNode for xslt_root | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | xsltInjection.py:50:24:50:32 | ControlFlowNode for xslt_root | This XSLT query depends on $@. | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value |
edges
| xslt.py:3:26:3:32 | ControlFlowNode for ImportMember | xslt.py:3:26:3:32 | ControlFlowNode for request | provenance | |
| xslt.py:3:26:3:32 | ControlFlowNode for request | xslt.py:10:17:10:23 | ControlFlowNode for request | provenance | |
@@ -122,10 +129,3 @@ nodes
| xsltInjection.py:46:38:46:48 | ControlFlowNode for xsltStrings [List element] | semmle.label | ControlFlowNode for xsltStrings [List element] |
| xsltInjection.py:50:24:50:32 | ControlFlowNode for xslt_root | semmle.label | ControlFlowNode for xslt_root |
subpaths
-#select
-| xslt.py:14:29:14:37 | ControlFlowNode for xslt_root | xslt.py:3:26:3:32 | ControlFlowNode for ImportMember | xslt.py:14:29:14:37 | ControlFlowNode for xslt_root | This XSLT query depends on $@. | xslt.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value |
-| xsltInjection.py:12:28:12:36 | ControlFlowNode for xslt_root | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | xsltInjection.py:12:28:12:36 | ControlFlowNode for xslt_root | This XSLT query depends on $@. | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value |
-| xsltInjection.py:21:29:21:37 | ControlFlowNode for xslt_root | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | xsltInjection.py:21:29:21:37 | ControlFlowNode for xslt_root | This XSLT query depends on $@. | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value |
-| xsltInjection.py:31:24:31:32 | ControlFlowNode for xslt_root | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | xsltInjection.py:31:24:31:32 | ControlFlowNode for xslt_root | This XSLT query depends on $@. | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value |
-| xsltInjection.py:40:24:40:32 | ControlFlowNode for xslt_root | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | xsltInjection.py:40:24:40:32 | ControlFlowNode for xslt_root | This XSLT query depends on $@. | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value |
-| xsltInjection.py:50:24:50:32 | ControlFlowNode for xslt_root | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | xsltInjection.py:50:24:50:32 | ControlFlowNode for xslt_root | This XSLT query depends on $@. | xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value |
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-091-XsltInjection/XsltInjection.qlref b/python/ql/test/experimental/query-tests/Security/CWE-091-XsltInjection/XsltInjection.qlref
index 4d432d461ca..5bde608133c 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-091-XsltInjection/XsltInjection.qlref
+++ b/python/ql/test/experimental/query-tests/Security/CWE-091-XsltInjection/XsltInjection.qlref
@@ -1 +1,2 @@
-experimental/Security/CWE-091/XsltInjection.ql
+query: experimental/Security/CWE-091/XsltInjection.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-091-XsltInjection/xslt.py b/python/ql/test/experimental/query-tests/Security/CWE-091-XsltInjection/xslt.py
index 1655916c7e0..6464d35811b 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-091-XsltInjection/xslt.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-091-XsltInjection/xslt.py
@@ -1,6 +1,6 @@
from lxml import etree
from io import StringIO
-from flask import Flask, request
+from flask import Flask, request # $ Source
app = Flask(__name__)
@@ -11,4 +11,4 @@ def bad():
xslt_root = etree.XML(xsltQuery)
f = StringIO('')
tree = etree.parse(f)
- result_tree = tree.xslt(xslt_root) # Not OK
+ result_tree = tree.xslt(xslt_root) # Not OK # $ Alert
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-091-XsltInjection/xsltInjection.py b/python/ql/test/experimental/query-tests/Security/CWE-091-XsltInjection/xsltInjection.py
index ddab954bbff..9f8a25f2e61 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-091-XsltInjection/xsltInjection.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-091-XsltInjection/xsltInjection.py
@@ -1,6 +1,6 @@
from lxml import etree
from io import StringIO
-from flask import Flask, request
+from flask import Flask, request # $ Source
app = Flask(__name__)
@@ -9,7 +9,7 @@ app = Flask(__name__)
def a():
xsltQuery = request.args.get('xml', '')
xslt_root = etree.XML(xsltQuery)
- transform = etree.XSLT(xslt_root) # Not OK
+ transform = etree.XSLT(xslt_root) # Not OK # $ Alert
@app.route("/xslt2")
@@ -18,7 +18,7 @@ def b():
xslt_root = etree.XML(xsltQuery)
f = StringIO('')
tree = etree.parse(f)
- result_tree = tree.xslt(xslt_root) # Not OK
+ result_tree = tree.xslt(xslt_root) # Not OK # $ Alert
@app.route("/xslt3")
@@ -28,7 +28,7 @@ def c():
f = StringIO('')
tree = etree.parse(f)
- result = tree.xslt(xslt_root, a="'A'") # Not OK
+ result = tree.xslt(xslt_root, a="'A'") # Not OK # $ Alert
@app.route("/xslt4")
def d():
@@ -37,7 +37,7 @@ def d():
f = StringIO('')
tree = etree.parse(f)
- result = tree.xslt(xslt_root, a="'A'") # Not OK
+ result = tree.xslt(xslt_root, a="'A'") # Not OK # $ Alert
@app.route("/xslt5")
def e():
@@ -47,7 +47,7 @@ def e():
f = StringIO('')
tree = etree.parse(f)
- result = tree.xslt(xslt_root, a="'A'") # Not OK
+ result = tree.xslt(xslt_root, a="'A'") # Not OK # $ Alert
@app.route("/xslt6")
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-094/Js2Py.expected b/python/ql/test/experimental/query-tests/Security/CWE-094/Js2Py.expected
index 7798cdda143..3fa27edd521 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-094/Js2Py.expected
+++ b/python/ql/test/experimental/query-tests/Security/CWE-094/Js2Py.expected
@@ -1,3 +1,5 @@
+#select
+| Js2PyTest.py:10:18:10:28 | ControlFlowNode for Fstring | Js2PyTest.py:9:10:9:22 | ControlFlowNode for Attribute | Js2PyTest.py:10:18:10:28 | ControlFlowNode for Fstring | This input to Js2Py depends on a $@. | Js2PyTest.py:9:10:9:22 | ControlFlowNode for Attribute | user-provided value |
edges
| Js2PyTest.py:9:5:9:6 | ControlFlowNode for jk | Js2PyTest.py:10:18:10:28 | ControlFlowNode for Fstring | provenance | |
| Js2PyTest.py:9:10:9:22 | ControlFlowNode for Attribute | Js2PyTest.py:9:5:9:6 | ControlFlowNode for jk | provenance | AdditionalTaintStep |
@@ -6,5 +8,3 @@ nodes
| Js2PyTest.py:9:10:9:22 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| Js2PyTest.py:10:18:10:28 | ControlFlowNode for Fstring | semmle.label | ControlFlowNode for Fstring |
subpaths
-#select
-| Js2PyTest.py:10:18:10:28 | ControlFlowNode for Fstring | Js2PyTest.py:9:10:9:22 | ControlFlowNode for Attribute | Js2PyTest.py:10:18:10:28 | ControlFlowNode for Fstring | This input to Js2Py depends on a $@. | Js2PyTest.py:9:10:9:22 | ControlFlowNode for Attribute | user-provided value |
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-094/Js2Py.qlref b/python/ql/test/experimental/query-tests/Security/CWE-094/Js2Py.qlref
index 457bfe2aacc..b88e9d7f392 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-094/Js2Py.qlref
+++ b/python/ql/test/experimental/query-tests/Security/CWE-094/Js2Py.qlref
@@ -1 +1,2 @@
-experimental/Security/CWE-094/Js2Py.ql
+query: experimental/Security/CWE-094/Js2Py.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-094/Js2PyTest.py b/python/ql/test/experimental/query-tests/Security/CWE-094/Js2PyTest.py
index f7aae16a9ee..d62cabef965 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-094/Js2PyTest.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-094/Js2PyTest.py
@@ -6,5 +6,5 @@ bp = flask.Blueprint("app", __name__, url_prefix="/")
@bp.route("/bad")
def bad():
- jk = flask.request.form["jk"]
- jk = eval_js(f"{jk} f()")
\ No newline at end of file
+ jk = flask.request.form["jk"] # $ Source
+ jk = eval_js(f"{jk} f()") # $ Alert
\ No newline at end of file
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-1236/CsvInjection.expected b/python/ql/test/experimental/query-tests/Security/CWE-1236/CsvInjection.expected
index 5152f7353f2..aa90dfaeea0 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-1236/CsvInjection.expected
+++ b/python/ql/test/experimental/query-tests/Security/CWE-1236/CsvInjection.expected
@@ -1,3 +1,7 @@
+#select
+| csv_bad.py:18:24:18:31 | ControlFlowNode for csv_data | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | csv_bad.py:18:24:18:31 | ControlFlowNode for csv_data | Csv injection might include code from $@. | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | this user input |
+| csv_bad.py:19:25:19:32 | ControlFlowNode for csv_data | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | csv_bad.py:19:25:19:32 | ControlFlowNode for csv_data | Csv injection might include code from $@. | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | this user input |
+| csv_bad.py:25:46:25:53 | ControlFlowNode for csv_data | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | csv_bad.py:25:46:25:53 | ControlFlowNode for csv_data | Csv injection might include code from $@. | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | this user input |
edges
| csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | csv_bad.py:9:19:9:25 | ControlFlowNode for request | provenance | |
| csv_bad.py:9:19:9:25 | ControlFlowNode for request | csv_bad.py:16:16:16:22 | ControlFlowNode for request | provenance | |
@@ -26,7 +30,3 @@ nodes
| csv_bad.py:24:16:24:38 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| csv_bad.py:25:46:25:53 | ControlFlowNode for csv_data | semmle.label | ControlFlowNode for csv_data |
subpaths
-#select
-| csv_bad.py:18:24:18:31 | ControlFlowNode for csv_data | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | csv_bad.py:18:24:18:31 | ControlFlowNode for csv_data | Csv injection might include code from $@. | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | this user input |
-| csv_bad.py:19:25:19:32 | ControlFlowNode for csv_data | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | csv_bad.py:19:25:19:32 | ControlFlowNode for csv_data | Csv injection might include code from $@. | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | this user input |
-| csv_bad.py:25:46:25:53 | ControlFlowNode for csv_data | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | csv_bad.py:25:46:25:53 | ControlFlowNode for csv_data | Csv injection might include code from $@. | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | this user input |
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-1236/CsvInjection.qlref b/python/ql/test/experimental/query-tests/Security/CWE-1236/CsvInjection.qlref
index d9cd7e9ca51..6fe779d1b36 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-1236/CsvInjection.qlref
+++ b/python/ql/test/experimental/query-tests/Security/CWE-1236/CsvInjection.qlref
@@ -1 +1,2 @@
-experimental/Security/CWE-1236/CsvInjection.ql
\ No newline at end of file
+query: experimental/Security/CWE-1236/CsvInjection.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-1236/csv_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-1236/csv_bad.py
index 6e204d1f3c5..91ce60b928b 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-1236/csv_bad.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-1236/csv_bad.py
@@ -6,7 +6,7 @@
import copy
import csv
from flask import Flask
-from flask import request
+from flask import request # $ Source
from typing import List
app = Flask(__name__)
@@ -15,14 +15,14 @@ app = Flask(__name__)
def bad1():
csv_data = request.args.get('csv')
csvWriter = csv.writer(open("test.csv", "wt"))
- csvWriter.writerow(csv_data) # bad
- csvWriter.writerows(csv_data) # bad
+ csvWriter.writerow(csv_data) # bad # $ Alert
+ csvWriter.writerows(csv_data) # bad # $ Alert
return "bad1"
@app.route('/bad2')
def bad2():
csv_data = request.args.get('csv')
- csvWriter = csv.DictWriter(f, fieldnames=csv_data) # bad
+ csvWriter = csv.DictWriter(f, fieldnames=csv_data) # bad # $ Alert
csvWriter.writeheader()
return "bad2"
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-176/UnicodeBypassValidation.qlref b/python/ql/test/experimental/query-tests/Security/CWE-176/UnicodeBypassValidation.qlref
index ee372b36840..710cbf1f46a 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-176/UnicodeBypassValidation.qlref
+++ b/python/ql/test/experimental/query-tests/Security/CWE-176/UnicodeBypassValidation.qlref
@@ -1 +1 @@
-experimental/Security/CWE-176/UnicodeBypassValidation.ql
+query: experimental/Security/CWE-176/UnicodeBypassValidation.ql
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.expected b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.expected
index 1577182b2dc..bd32259294e 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.expected
+++ b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.expected
@@ -1,3 +1,6 @@
+#select
+| TimingAttackAgainstHash.py:27:24:27:32 | ControlFlowNode for signature | TimingAttackAgainstHash.py:26:17:26:41 | ControlFlowNode for Attribute() | TimingAttackAgainstHash.py:27:24:27:32 | ControlFlowNode for signature | Possible Timing attack against $@ validation. | TimingAttackAgainstHash.py:26:17:26:41 | ControlFlowNode for Attribute() | signature message |
+| TimingAttackAgainstHash.py:37:19:37:48 | ControlFlowNode for sign() | TimingAttackAgainstHash.py:30:12:30:47 | ControlFlowNode for Attribute() | TimingAttackAgainstHash.py:37:19:37:48 | ControlFlowNode for sign() | Possible Timing attack against $@ validation. | TimingAttackAgainstHash.py:30:12:30:47 | ControlFlowNode for Attribute() | MAC message |
edges
| TimingAttackAgainstHash.py:26:5:26:13 | ControlFlowNode for signature | TimingAttackAgainstHash.py:27:24:27:32 | ControlFlowNode for signature | provenance | |
| TimingAttackAgainstHash.py:26:17:26:41 | ControlFlowNode for Attribute() | TimingAttackAgainstHash.py:26:5:26:13 | ControlFlowNode for signature | provenance | |
@@ -9,6 +12,3 @@ nodes
| TimingAttackAgainstHash.py:30:12:30:47 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| TimingAttackAgainstHash.py:37:19:37:48 | ControlFlowNode for sign() | semmle.label | ControlFlowNode for sign() |
subpaths
-#select
-| TimingAttackAgainstHash.py:27:24:27:32 | ControlFlowNode for signature | TimingAttackAgainstHash.py:26:17:26:41 | ControlFlowNode for Attribute() | TimingAttackAgainstHash.py:27:24:27:32 | ControlFlowNode for signature | Possible Timing attack against $@ validation. | TimingAttackAgainstHash.py:26:17:26:41 | ControlFlowNode for Attribute() | signature message |
-| TimingAttackAgainstHash.py:37:19:37:48 | ControlFlowNode for sign() | TimingAttackAgainstHash.py:30:12:30:47 | ControlFlowNode for Attribute() | TimingAttackAgainstHash.py:37:19:37:48 | ControlFlowNode for sign() | Possible Timing attack against $@ validation. | TimingAttackAgainstHash.py:30:12:30:47 | ControlFlowNode for Attribute() | MAC message |
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.qlref b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.qlref
index 73a8e6960ef..5ac00932072 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.qlref
+++ b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.qlref
@@ -1 +1,2 @@
-experimental/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.ql
+query: experimental/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHash/TimingAttackAgainstHash.expected b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHash/TimingAttackAgainstHash.expected
index 0b7b2de8ddb..0d3ebb1cf11 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHash/TimingAttackAgainstHash.expected
+++ b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHash/TimingAttackAgainstHash.expected
@@ -1,3 +1,4 @@
+#select
edges
| TimingAttackAgainstHash.py:26:5:26:13 | ControlFlowNode for signature | TimingAttackAgainstHash.py:27:24:27:32 | ControlFlowNode for signature | provenance | |
| TimingAttackAgainstHash.py:26:17:26:41 | ControlFlowNode for Attribute() | TimingAttackAgainstHash.py:26:5:26:13 | ControlFlowNode for signature | provenance | |
@@ -9,4 +10,3 @@ nodes
| TimingAttackAgainstHash.py:30:12:30:47 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| TimingAttackAgainstHash.py:37:19:37:48 | ControlFlowNode for sign() | semmle.label | ControlFlowNode for sign() |
subpaths
-#select
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHash/TimingAttackAgainstHash.py b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHash/TimingAttackAgainstHash.py
index 1d312f028eb..c5084b78e80 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHash/TimingAttackAgainstHash.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHash/TimingAttackAgainstHash.py
@@ -23,18 +23,18 @@ def UnsafeCheckSignature(expected):
message = b'To be signed'
key = RSA.import_key(open('private_key.der').read())
h = SHA256.new(message)
- signature = pkcs1_15.new(key).sign(h)
- return expected == signature
+ signature = pkcs1_15.new(key).sign(h) # $ Source[py/possible-timing-attack-against-hash]
+ return expected == signature # $ Alert[py/possible-timing-attack-against-hash]
def sign(pre_key, msg, alg):
- return hmac.new(pre_key, msg, alg).digest()
+ return hmac.new(pre_key, msg, alg).digest() # $ Source[py/possible-timing-attack-against-hash]
def verifyGood(msg, sig):
return constant_time_string_compare(sig, sign(key, msg, hashlib.sha256)) #good
def verifyBad(msg, sig):
key = "e179017a-62b0-4996-8a38-e91aa9f1"
- return sig == sign(key, msg, hashlib.sha256) #bad
+ return sig == sign(key, msg, hashlib.sha256) #bad # $ Alert[py/possible-timing-attack-against-hash]
def constant_time_string_compare(a, b):
if len(a) != len(b):
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHash/TimingAttackAgainstHash.qlref b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHash/TimingAttackAgainstHash.qlref
index 50c9d84b1f9..2829d76e85d 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHash/TimingAttackAgainstHash.qlref
+++ b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHash/TimingAttackAgainstHash.qlref
@@ -1 +1,2 @@
-experimental/Security/CWE-208/TimingAttackAgainstHash/TimingAttackAgainstHash.ql
+query: experimental/Security/CWE-208/TimingAttackAgainstHash/TimingAttackAgainstHash.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeader.py b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeader.py
index 211c36274d7..591764ed4f8 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeader.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeader.py
@@ -11,7 +11,7 @@ app = Flask(__name__)
@app.route('/bad')
def bad():
- if not request.headers.get('X-Auth-Token') == "token":
+ if not request.headers.get('X-Auth-Token') == "token": # $ Alert
raise Exception('bad token')
return 'bad'
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeaderValue.expected b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeaderValue.expected
index 14c8b8bf1eb..25e04cafb6f 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeaderValue.expected
+++ b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeaderValue.expected
@@ -1,6 +1,6 @@
+#select
+| TimingAttackAgainstHeader.py:14:12:14:46 | ControlFlowNode for Attribute() | TimingAttackAgainstHeader.py:14:12:14:46 | ControlFlowNode for Attribute() | TimingAttackAgainstHeader.py:14:12:14:46 | ControlFlowNode for Attribute() | Timing attack against $@ validation. | TimingAttackAgainstHeader.py:14:12:14:46 | ControlFlowNode for Attribute() | client-supplied token |
edges
nodes
| TimingAttackAgainstHeader.py:14:12:14:46 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
subpaths
-#select
-| TimingAttackAgainstHeader.py:14:12:14:46 | ControlFlowNode for Attribute() | TimingAttackAgainstHeader.py:14:12:14:46 | ControlFlowNode for Attribute() | TimingAttackAgainstHeader.py:14:12:14:46 | ControlFlowNode for Attribute() | Timing attack against $@ validation. | TimingAttackAgainstHeader.py:14:12:14:46 | ControlFlowNode for Attribute() | client-supplied token |
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeaderValue.qlref b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeaderValue.qlref
index 9da35da9d6d..0d31d85dc3f 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeaderValue.qlref
+++ b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeaderValue.qlref
@@ -1 +1,2 @@
-experimental/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeaderValue.ql
+query: experimental/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeaderValue.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.expected b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.expected
index 80b07434896..b65708ca34e 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.expected
+++ b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.expected
@@ -1,9 +1,9 @@
+#select
+| TimingAttackAgainstSensitiveInfo.py:16:16:16:23 | ControlFlowNode for password | TimingAttackAgainstSensitiveInfo.py:15:9:15:16 | ControlFlowNode for password | TimingAttackAgainstSensitiveInfo.py:16:16:16:23 | ControlFlowNode for password | Timing attack against $@ validation. | TimingAttackAgainstSensitiveInfo.py:15:9:15:16 | ControlFlowNode for password | client-supplied token |
+| TimingAttackAgainstSensitiveInfo.py:16:16:16:23 | ControlFlowNode for password | TimingAttackAgainstSensitiveInfo.py:16:16:16:23 | ControlFlowNode for password | TimingAttackAgainstSensitiveInfo.py:16:16:16:23 | ControlFlowNode for password | Timing attack against $@ validation. | TimingAttackAgainstSensitiveInfo.py:16:16:16:23 | ControlFlowNode for password | client-supplied token |
edges
| TimingAttackAgainstSensitiveInfo.py:15:9:15:16 | ControlFlowNode for password | TimingAttackAgainstSensitiveInfo.py:16:16:16:23 | ControlFlowNode for password | provenance | |
nodes
| TimingAttackAgainstSensitiveInfo.py:15:9:15:16 | ControlFlowNode for password | semmle.label | ControlFlowNode for password |
| TimingAttackAgainstSensitiveInfo.py:16:16:16:23 | ControlFlowNode for password | semmle.label | ControlFlowNode for password |
subpaths
-#select
-| TimingAttackAgainstSensitiveInfo.py:16:16:16:23 | ControlFlowNode for password | TimingAttackAgainstSensitiveInfo.py:15:9:15:16 | ControlFlowNode for password | TimingAttackAgainstSensitiveInfo.py:16:16:16:23 | ControlFlowNode for password | Timing attack against $@ validation. | TimingAttackAgainstSensitiveInfo.py:15:9:15:16 | ControlFlowNode for password | client-supplied token |
-| TimingAttackAgainstSensitiveInfo.py:16:16:16:23 | ControlFlowNode for password | TimingAttackAgainstSensitiveInfo.py:16:16:16:23 | ControlFlowNode for password | TimingAttackAgainstSensitiveInfo.py:16:16:16:23 | ControlFlowNode for password | Timing attack against $@ validation. | TimingAttackAgainstSensitiveInfo.py:16:16:16:23 | ControlFlowNode for password | client-supplied token |
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.qlref b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.qlref
index acfe13f6aad..bd9d8272f98 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.qlref
+++ b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.qlref
@@ -1 +1,2 @@
-experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.ql
+query: experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstSensitiveInfo/TimingAttackAgainstSensitiveInfo.py b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstSensitiveInfo/TimingAttackAgainstSensitiveInfo.py
index a34b3b7c5ae..4619821174e 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstSensitiveInfo/TimingAttackAgainstSensitiveInfo.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstSensitiveInfo/TimingAttackAgainstSensitiveInfo.py
@@ -12,8 +12,8 @@ app = Flask(__name__)
@app.route('/bad', methods = ['POST', 'GET'])
def bad():
if request.method == 'POST':
- password = request.form['pwd']
- return password == "1234"
+ password = request.form['pwd'] # $ Source
+ return password == "1234" # $ Alert
@app.route('/good', methods = ['POST', 'GET'])
def good():
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-287-ConstantSecretKey/ConstantSecretKey.expected b/python/ql/test/experimental/query-tests/Security/CWE-287-ConstantSecretKey/ConstantSecretKey.expected
index 00c32be4267..2054ba4a231 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-287-ConstantSecretKey/ConstantSecretKey.expected
+++ b/python/ql/test/experimental/query-tests/Security/CWE-287-ConstantSecretKey/ConstantSecretKey.expected
@@ -1,3 +1,13 @@
+#select
+| app_safe.py:5:28:5:37 | ControlFlowNode for StringLiteral | app_safe.py:5:28:5:37 | ControlFlowNode for StringLiteral | app_safe.py:5:28:5:37 | ControlFlowNode for StringLiteral | The SECRET_KEY config variable is assigned by $@. | app_safe.py:5:28:5:37 | ControlFlowNode for StringLiteral | this constant String |
+| app_unsafe.py:5:28:5:36 | ControlFlowNode for aConstant | app_unsafe.py:4:13:4:23 | ControlFlowNode for StringLiteral | app_unsafe.py:5:28:5:36 | ControlFlowNode for aConstant | The SECRET_KEY config variable is assigned by $@. | app_unsafe.py:4:13:4:23 | ControlFlowNode for StringLiteral | this constant String |
+| app_unsafe.py:6:18:6:26 | ControlFlowNode for aConstant | app_unsafe.py:4:13:4:23 | ControlFlowNode for StringLiteral | app_unsafe.py:6:18:6:26 | ControlFlowNode for aConstant | The SECRET_KEY config variable is assigned by $@. | app_unsafe.py:4:13:4:23 | ControlFlowNode for StringLiteral | this constant String |
+| app_unsafe.py:7:30:7:38 | ControlFlowNode for aConstant | app_unsafe.py:4:13:4:23 | ControlFlowNode for StringLiteral | app_unsafe.py:7:30:7:38 | ControlFlowNode for aConstant | The SECRET_KEY config variable is assigned by $@. | app_unsafe.py:4:13:4:23 | ControlFlowNode for StringLiteral | this constant String |
+| app_unsafe.py:8:36:8:44 | ControlFlowNode for aConstant | app_unsafe.py:4:13:4:23 | ControlFlowNode for StringLiteral | app_unsafe.py:8:36:8:44 | ControlFlowNode for aConstant | The SECRET_KEY config variable is assigned by $@. | app_unsafe.py:4:13:4:23 | ControlFlowNode for StringLiteral | this constant String |
+| config2.py:5:14:5:24 | ControlFlowNode for StringLiteral | config2.py:5:14:5:24 | ControlFlowNode for StringLiteral | config2.py:5:14:5:24 | ControlFlowNode for StringLiteral | The SECRET_KEY config variable is assigned by $@. | config2.py:5:14:5:24 | ControlFlowNode for StringLiteral | this constant String |
+| config.py:12:18:12:26 | ControlFlowNode for aConstant | config.py:7:13:7:23 | ControlFlowNode for StringLiteral | config.py:12:18:12:26 | ControlFlowNode for aConstant | The SECRET_KEY config variable is assigned by $@. | config.py:7:13:7:23 | ControlFlowNode for StringLiteral | this constant String |
+| config.py:17:18:17:47 | ControlFlowNode for Attribute() | config.py:7:13:7:23 | ControlFlowNode for StringLiteral | config.py:17:18:17:47 | ControlFlowNode for Attribute() | The SECRET_KEY config variable is assigned by $@. | config.py:7:13:7:23 | ControlFlowNode for StringLiteral | this constant String |
+| config.py:18:18:18:52 | ControlFlowNode for Attribute() | config.py:7:13:7:23 | ControlFlowNode for StringLiteral | config.py:18:18:18:52 | ControlFlowNode for Attribute() | The SECRET_KEY config variable is assigned by $@. | config.py:7:13:7:23 | ControlFlowNode for StringLiteral | this constant String |
edges
| app_unsafe.py:4:1:4:9 | ControlFlowNode for aConstant | app_unsafe.py:5:28:5:36 | ControlFlowNode for aConstant | provenance | |
| app_unsafe.py:4:1:4:9 | ControlFlowNode for aConstant | app_unsafe.py:6:18:6:26 | ControlFlowNode for aConstant | provenance | |
@@ -32,13 +42,3 @@ nodes
| config.py:18:18:18:52 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| config.py:18:43:18:51 | ControlFlowNode for aConstant | semmle.label | ControlFlowNode for aConstant |
subpaths
-#select
-| app_safe.py:5:28:5:37 | ControlFlowNode for StringLiteral | app_safe.py:5:28:5:37 | ControlFlowNode for StringLiteral | app_safe.py:5:28:5:37 | ControlFlowNode for StringLiteral | The SECRET_KEY config variable is assigned by $@. | app_safe.py:5:28:5:37 | ControlFlowNode for StringLiteral | this constant String |
-| app_unsafe.py:5:28:5:36 | ControlFlowNode for aConstant | app_unsafe.py:4:13:4:23 | ControlFlowNode for StringLiteral | app_unsafe.py:5:28:5:36 | ControlFlowNode for aConstant | The SECRET_KEY config variable is assigned by $@. | app_unsafe.py:4:13:4:23 | ControlFlowNode for StringLiteral | this constant String |
-| app_unsafe.py:6:18:6:26 | ControlFlowNode for aConstant | app_unsafe.py:4:13:4:23 | ControlFlowNode for StringLiteral | app_unsafe.py:6:18:6:26 | ControlFlowNode for aConstant | The SECRET_KEY config variable is assigned by $@. | app_unsafe.py:4:13:4:23 | ControlFlowNode for StringLiteral | this constant String |
-| app_unsafe.py:7:30:7:38 | ControlFlowNode for aConstant | app_unsafe.py:4:13:4:23 | ControlFlowNode for StringLiteral | app_unsafe.py:7:30:7:38 | ControlFlowNode for aConstant | The SECRET_KEY config variable is assigned by $@. | app_unsafe.py:4:13:4:23 | ControlFlowNode for StringLiteral | this constant String |
-| app_unsafe.py:8:36:8:44 | ControlFlowNode for aConstant | app_unsafe.py:4:13:4:23 | ControlFlowNode for StringLiteral | app_unsafe.py:8:36:8:44 | ControlFlowNode for aConstant | The SECRET_KEY config variable is assigned by $@. | app_unsafe.py:4:13:4:23 | ControlFlowNode for StringLiteral | this constant String |
-| config2.py:5:14:5:24 | ControlFlowNode for StringLiteral | config2.py:5:14:5:24 | ControlFlowNode for StringLiteral | config2.py:5:14:5:24 | ControlFlowNode for StringLiteral | The SECRET_KEY config variable is assigned by $@. | config2.py:5:14:5:24 | ControlFlowNode for StringLiteral | this constant String |
-| config.py:12:18:12:26 | ControlFlowNode for aConstant | config.py:7:13:7:23 | ControlFlowNode for StringLiteral | config.py:12:18:12:26 | ControlFlowNode for aConstant | The SECRET_KEY config variable is assigned by $@. | config.py:7:13:7:23 | ControlFlowNode for StringLiteral | this constant String |
-| config.py:17:18:17:47 | ControlFlowNode for Attribute() | config.py:7:13:7:23 | ControlFlowNode for StringLiteral | config.py:17:18:17:47 | ControlFlowNode for Attribute() | The SECRET_KEY config variable is assigned by $@. | config.py:7:13:7:23 | ControlFlowNode for StringLiteral | this constant String |
-| config.py:18:18:18:52 | ControlFlowNode for Attribute() | config.py:7:13:7:23 | ControlFlowNode for StringLiteral | config.py:18:18:18:52 | ControlFlowNode for Attribute() | The SECRET_KEY config variable is assigned by $@. | config.py:7:13:7:23 | ControlFlowNode for StringLiteral | this constant String |
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-287-ConstantSecretKey/ConstantSecretKey.qlref b/python/ql/test/experimental/query-tests/Security/CWE-287-ConstantSecretKey/ConstantSecretKey.qlref
index e77b304f62c..535dfacbac4 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-287-ConstantSecretKey/ConstantSecretKey.qlref
+++ b/python/ql/test/experimental/query-tests/Security/CWE-287-ConstantSecretKey/ConstantSecretKey.qlref
@@ -1 +1,2 @@
-experimental/Security/CWE-287-ConstantSecretKey/WebAppConstantSecretKey.ql
+query: experimental/Security/CWE-287-ConstantSecretKey/WebAppConstantSecretKey.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-287-ConstantSecretKey/app_safe.py b/python/ql/test/experimental/query-tests/Security/CWE-287-ConstantSecretKey/app_safe.py
index 442a23e2c3a..3fcb38acbf9 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-287-ConstantSecretKey/app_safe.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-287-ConstantSecretKey/app_safe.py
@@ -2,7 +2,7 @@ from flask import Flask, session
from flask_session import Session
app = Flask(__name__)
-app.config['SECRET_KEY'] = 'CHANGEME'
+app.config['SECRET_KEY'] = 'CHANGEME' # $ Alert
Session(app)
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-287-ConstantSecretKey/app_unsafe.py b/python/ql/test/experimental/query-tests/Security/CWE-287-ConstantSecretKey/app_unsafe.py
index 5aeeb6f7003..c108dfd4561 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-287-ConstantSecretKey/app_unsafe.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-287-ConstantSecretKey/app_unsafe.py
@@ -1,11 +1,11 @@
from flask import Flask, session
app = Flask(__name__)
-aConstant = 'CHANGEME1'
-app.config['SECRET_KEY'] = aConstant
-app.secret_key = aConstant
-app.config.update(SECRET_KEY=aConstant)
-app.config.from_mapping(SECRET_KEY=aConstant)
+aConstant = 'CHANGEME1' # $ Source
+app.config['SECRET_KEY'] = aConstant # $ Alert
+app.secret_key = aConstant # $ Alert
+app.config.update(SECRET_KEY=aConstant) # $ Alert
+app.config.from_mapping(SECRET_KEY=aConstant) # $ Alert
app.config.from_pyfile("config.py")
app.config.from_object('config.Config')
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-287-ConstantSecretKey/config.py b/python/ql/test/experimental/query-tests/Security/CWE-287-ConstantSecretKey/config.py
index 1a512c0d9f0..12dacb516e6 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-287-ConstantSecretKey/config.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-287-ConstantSecretKey/config.py
@@ -4,16 +4,16 @@ import os
import random
FLASK_DEBUG = True
-aConstant = 'CHANGEME2'
+aConstant = 'CHANGEME2' # $ Source
class Config:
SECRET_KEY = environ.get("envKey")
- SECRET_KEY = aConstant
+ SECRET_KEY = aConstant # $ Alert
SECRET_KEY = os.getenv('envKey')
SECRET_KEY = os.environ.get('envKey')
SECRET_KEY = os.environ.get('envKey', random.randint)
SECRET_KEY = os.getenv('envKey', random.randint)
- SECRET_KEY = os.getenv('envKey', aConstant)
- SECRET_KEY = os.environ.get('envKey', aConstant)
+ SECRET_KEY = os.getenv('envKey', aConstant) # $ Alert
+ SECRET_KEY = os.environ.get('envKey', aConstant) # $ Alert
SECRET_KEY = os.environ['envKey']
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-287-ConstantSecretKey/config2.py b/python/ql/test/experimental/query-tests/Security/CWE-287-ConstantSecretKey/config2.py
index dc3508783e2..96b08fead12 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-287-ConstantSecretKey/config2.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-287-ConstantSecretKey/config2.py
@@ -2,4 +2,4 @@
# General Config
FLASK_DEBUG = True
-SECRET_KEY = "CHANGEME5"
+SECRET_KEY = "CHANGEME5" # $ Alert
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-287/ImproperLdapAuth.qlref b/python/ql/test/experimental/query-tests/Security/CWE-287/ImproperLdapAuth.qlref
index 9f5c6e4c43f..edd5c17e2b1 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-287/ImproperLdapAuth.qlref
+++ b/python/ql/test/experimental/query-tests/Security/CWE-287/ImproperLdapAuth.qlref
@@ -1 +1,2 @@
-experimental/Security/CWE-287/ImproperLdapAuth.ql
+query: experimental/Security/CWE-287/ImproperLdapAuth.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-287/auth_bad_2.py b/python/ql/test/experimental/query-tests/Security/CWE-287/auth_bad_2.py
index d37cc09cfd0..ef274090f91 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-287/auth_bad_2.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-287/auth_bad_2.py
@@ -16,7 +16,7 @@ def simple_bind_example():
search_filter = "(user={})".format(ldap.filter.escape_filter_chars(request.args['search']))
ldap_connection = ldap.initialize("ldap://127.0.0.1:1337")
- ldap_connection.simple_bind('cn=root')
+ ldap_connection.simple_bind('cn=root') # $ Alert
user = ldap_connection.search_s(dn, ldap.SCOPE_SUBTREE, search_filter)
@@ -30,7 +30,7 @@ def simple_bind_s_example():
search_filter = "(user={})".format(ldap.filter.escape_filter_chars(request.args['search']))
ldap_connection = ldap.initialize("ldap://127.0.0.1:1337")
- ldap_connection.simple_bind_s('cn=root')
+ ldap_connection.simple_bind_s('cn=root') # $ Alert
user = ldap_connection.search_s(dn, ldap.SCOPE_SUBTREE, search_filter)
@@ -44,7 +44,7 @@ def bind_s_example():
search_filter = "(user={})".format(ldap.filter.escape_filter_chars(request.args['search']))
ldap_connection = ldap.initialize("ldap://127.0.0.1:1337")
- ldap_connection.bind_s('cn=root', None)
+ ldap_connection.bind_s('cn=root', None) # $ Alert
user = ldap_connection.search_s(dn, ldap.SCOPE_SUBTREE, search_filter)
@app.route("/bind_s_example")
@@ -57,7 +57,7 @@ def bind_s_example_kwargs():
search_filter = "(user={})".format(ldap.filter.escape_filter_chars(request.args['search']))
ldap_connection = ldap.initialize("ldap://127.0.0.1:1337")
- ldap_connection.bind_s(who='cn=root', cred=None)
+ ldap_connection.bind_s(who='cn=root', cred=None) # $ Alert
user = ldap_connection.search_s(dn, ldap.SCOPE_SUBTREE, search_filter)
@app.route("/bind_example")
@@ -70,7 +70,7 @@ def bind_example():
search_filter = "(user={})".format(ldap.filter.escape_filter_chars(request.args['search']))
ldap_connection = ldap.initialize("ldap://127.0.0.1:1337")
- ldap_connection.bind('cn=root', "")
+ ldap_connection.bind('cn=root', "") # $ Alert
user = ldap_connection.search_s(dn, ldap.SCOPE_SUBTREE, search_filter)
@@ -84,7 +84,7 @@ def bind_example():
search_filter = "(user={})".format(ldap.filter.escape_filter_chars(request.args['search']))
ldap_connection = ldap.initialize("ldap://127.0.0.1:1337")
- ldap_connection.bind(who='cn=root', cred="")
+ ldap_connection.bind(who='cn=root', cred="") # $ Alert
user = ldap_connection.search_s(dn, ldap.SCOPE_SUBTREE, search_filter)
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-287/auth_bad_3.py b/python/ql/test/experimental/query-tests/Security/CWE-287/auth_bad_3.py
index 2500b4cadb6..3b99754ec40 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-287/auth_bad_3.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-287/auth_bad_3.py
@@ -16,7 +16,7 @@ def passwordNone():
search_filter = "(user={})".format(escape_filter_chars(request.args['search']))
srv = Server('servername', get_info=ALL)
- conn = Connection(srv, 'user_dn', None)
+ conn = Connection(srv, 'user_dn', None) # $ Alert
status, result, response, _ = conn.search(dn, search_filter)
@@ -30,7 +30,7 @@ def passwordNoneKwargs():
search_filter = "(user={})".format(escape_filter_chars(request.args['search']))
srv = Server('servername', get_info=ALL)
- conn = Connection(srv, user='user_dn', password=None)
+ conn = Connection(srv, user='user_dn', password=None) # $ Alert
status, result, response, _ = conn.search(dn, search_filter)
@app.route("/passwordEmpty")
@@ -43,7 +43,7 @@ def passwordEmpty():
search_filter = "(user={})".format(escape_filter_chars(request.args['search']))
srv = Server('servername', get_info=ALL)
- conn = Connection(srv, user='user_dn', password="")
+ conn = Connection(srv, user='user_dn', password="") # $ Alert
status, result, response, _ = conn.search(dn, search_filter)
@@ -57,7 +57,7 @@ def notPassword():
search_filter = "(user={})".format(escape_filter_chars(request.args['search']))
srv = Server('servername', get_info=ALL)
- conn = Connection(srv, user='user_dn')
+ conn = Connection(srv, user='user_dn') # $ Alert
status, result, response, _ = conn.search(dn, search_filter)
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-327-UnsafeUsageOfClientSideEncryptionVersion/UnsafeUsageOfClientSideEncryptionVersion.expected b/python/ql/test/experimental/query-tests/Security/CWE-327-UnsafeUsageOfClientSideEncryptionVersion/UnsafeUsageOfClientSideEncryptionVersion.expected
index 097e3580fb1..8ffc7ac31d9 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-327-UnsafeUsageOfClientSideEncryptionVersion/UnsafeUsageOfClientSideEncryptionVersion.expected
+++ b/python/ql/test/experimental/query-tests/Security/CWE-327-UnsafeUsageOfClientSideEncryptionVersion/UnsafeUsageOfClientSideEncryptionVersion.expected
@@ -1,3 +1,9 @@
+#select
+| test.py:11:9:11:19 | ControlFlowNode for blob_client | test.py:3:7:3:51 | ControlFlowNode for Attribute() | test.py:11:9:11:19 | ControlFlowNode for blob_client | Unsafe usage of v1 version of Azure Storage client-side encryption |
+| test.py:21:9:21:19 | ControlFlowNode for blob_client | test.py:15:27:15:71 | ControlFlowNode for Attribute() | test.py:21:9:21:19 | ControlFlowNode for blob_client | Unsafe usage of v1 version of Azure Storage client-side encryption |
+| test.py:31:9:31:19 | ControlFlowNode for blob_client | test.py:25:24:25:66 | ControlFlowNode for Attribute() | test.py:31:9:31:19 | ControlFlowNode for blob_client | Unsafe usage of v1 version of Azure Storage client-side encryption |
+| test.py:43:9:43:19 | ControlFlowNode for blob_client | test.py:3:7:3:51 | ControlFlowNode for Attribute() | test.py:43:9:43:19 | ControlFlowNode for blob_client | Unsafe usage of v1 version of Azure Storage client-side encryption |
+| test.py:75:9:75:10 | ControlFlowNode for bc | test.py:3:7:3:51 | ControlFlowNode for Attribute() | test.py:75:9:75:10 | ControlFlowNode for bc | Unsafe usage of v1 version of Azure Storage client-side encryption |
edges
| test.py:3:1:3:3 | ControlFlowNode for BSC | test.py:7:19:7:21 | ControlFlowNode for BSC | provenance | |
| test.py:3:1:3:3 | ControlFlowNode for BSC | test.py:35:19:35:21 | ControlFlowNode for BSC | provenance | |
@@ -86,9 +92,3 @@ nodes
| test.py:73:10:73:33 | ControlFlowNode for get_unsafe_blob_client() | semmle.label | ControlFlowNode for get_unsafe_blob_client() |
| test.py:75:9:75:10 | ControlFlowNode for bc | semmle.label | ControlFlowNode for bc |
subpaths
-#select
-| test.py:11:9:11:19 | ControlFlowNode for blob_client | test.py:3:7:3:51 | ControlFlowNode for Attribute() | test.py:11:9:11:19 | ControlFlowNode for blob_client | Unsafe usage of v1 version of Azure Storage client-side encryption |
-| test.py:21:9:21:19 | ControlFlowNode for blob_client | test.py:15:27:15:71 | ControlFlowNode for Attribute() | test.py:21:9:21:19 | ControlFlowNode for blob_client | Unsafe usage of v1 version of Azure Storage client-side encryption |
-| test.py:31:9:31:19 | ControlFlowNode for blob_client | test.py:25:24:25:66 | ControlFlowNode for Attribute() | test.py:31:9:31:19 | ControlFlowNode for blob_client | Unsafe usage of v1 version of Azure Storage client-side encryption |
-| test.py:43:9:43:19 | ControlFlowNode for blob_client | test.py:3:7:3:51 | ControlFlowNode for Attribute() | test.py:43:9:43:19 | ControlFlowNode for blob_client | Unsafe usage of v1 version of Azure Storage client-side encryption |
-| test.py:75:9:75:10 | ControlFlowNode for bc | test.py:3:7:3:51 | ControlFlowNode for Attribute() | test.py:75:9:75:10 | ControlFlowNode for bc | Unsafe usage of v1 version of Azure Storage client-side encryption |
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-327-UnsafeUsageOfClientSideEncryptionVersion/UnsafeUsageOfClientSideEncryptionVersion.qlref b/python/ql/test/experimental/query-tests/Security/CWE-327-UnsafeUsageOfClientSideEncryptionVersion/UnsafeUsageOfClientSideEncryptionVersion.qlref
index b737b32c815..b5ed8a0d636 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-327-UnsafeUsageOfClientSideEncryptionVersion/UnsafeUsageOfClientSideEncryptionVersion.qlref
+++ b/python/ql/test/experimental/query-tests/Security/CWE-327-UnsafeUsageOfClientSideEncryptionVersion/UnsafeUsageOfClientSideEncryptionVersion.qlref
@@ -1 +1,2 @@
-experimental/Security/CWE-327/Azure/UnsafeUsageOfClientSideEncryptionVersion.ql
+query: experimental/Security/CWE-327/Azure/UnsafeUsageOfClientSideEncryptionVersion.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-327-UnsafeUsageOfClientSideEncryptionVersion/test.py b/python/ql/test/experimental/query-tests/Security/CWE-327-UnsafeUsageOfClientSideEncryptionVersion/test.py
index 32fa60c6193..8cb7d2b7794 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-327-UnsafeUsageOfClientSideEncryptionVersion/test.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-327-UnsafeUsageOfClientSideEncryptionVersion/test.py
@@ -1,6 +1,6 @@
from azure.storage.blob import BlobServiceClient, ContainerClient, BlobClient
-BSC = BlobServiceClient.from_connection_string(...)
+BSC = BlobServiceClient.from_connection_string(...) # $ Source
def unsafe():
# does not set encryption_version to 2.0, default is unsafe
@@ -8,27 +8,27 @@ def unsafe():
blob_client.require_encryption = True
blob_client.key_encryption_key = ...
with open("decryptedcontentfile.txt", "rb") as stream:
- blob_client.upload_blob(stream) # BAD
+ blob_client.upload_blob(stream) # BAD # $ Alert
def unsafe_setting_on_blob_service_client():
- blob_service_client = BlobServiceClient.from_connection_string(...)
+ blob_service_client = BlobServiceClient.from_connection_string(...) # $ Source
blob_service_client.require_encryption = True
blob_service_client.key_encryption_key = ...
blob_client = blob_service_client.get_blob_client(...)
with open("decryptedcontentfile.txt", "rb") as stream:
- blob_client.upload_blob(stream)
+ blob_client.upload_blob(stream) # $ Alert
def unsafe_setting_on_container_client():
- container_client = ContainerClient.from_connection_string(...)
+ container_client = ContainerClient.from_connection_string(...) # $ Source
container_client.require_encryption = True
container_client.key_encryption_key = ...
blob_client = container_client.get_blob_client(...)
with open("decryptedcontentfile.txt", "rb") as stream:
- blob_client.upload_blob(stream)
+ blob_client.upload_blob(stream) # $ Alert
def potentially_unsafe(use_new_version=False):
@@ -40,7 +40,7 @@ def potentially_unsafe(use_new_version=False):
blob_client.encryption_version = '2.0'
with open("decryptedcontentfile.txt", "rb") as stream:
- blob_client.upload_blob(stream) # BAD
+ blob_client.upload_blob(stream) # BAD # $ Alert
def safe():
@@ -72,7 +72,7 @@ def get_unsafe_blob_client():
def unsafe_with_calls():
bc = get_unsafe_blob_client()
with open("decryptedcontentfile.txt", "rb") as stream:
- bc.upload_blob(stream) # BAD
+ bc.upload_blob(stream) # BAD # $ Alert
def get_safe_blob_client():
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-338/InsecureRandomness.expected b/python/ql/test/experimental/query-tests/Security/CWE-338/InsecureRandomness.expected
index 29ecd398a0a..da6e1c5aa1f 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-338/InsecureRandomness.expected
+++ b/python/ql/test/experimental/query-tests/Security/CWE-338/InsecureRandomness.expected
@@ -1,6 +1,6 @@
+#select
+| InsecureRandomness.py:5:12:5:26 | ControlFlowNode for Attribute() | InsecureRandomness.py:5:12:5:26 | ControlFlowNode for Attribute() | InsecureRandomness.py:5:12:5:26 | ControlFlowNode for Attribute() | Cryptographically insecure $@ in a security context. | InsecureRandomness.py:5:12:5:26 | ControlFlowNode for Attribute() | random value |
edges
nodes
| InsecureRandomness.py:5:12:5:26 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
subpaths
-#select
-| InsecureRandomness.py:5:12:5:26 | ControlFlowNode for Attribute() | InsecureRandomness.py:5:12:5:26 | ControlFlowNode for Attribute() | InsecureRandomness.py:5:12:5:26 | ControlFlowNode for Attribute() | Cryptographically insecure $@ in a security context. | InsecureRandomness.py:5:12:5:26 | ControlFlowNode for Attribute() | random value |
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-338/InsecureRandomness.py b/python/ql/test/experimental/query-tests/Security/CWE-338/InsecureRandomness.py
index 9f043954967..ee94baf9eee 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-338/InsecureRandomness.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-338/InsecureRandomness.py
@@ -2,4 +2,4 @@ import random
def generatePassword():
# BAD: the random is not cryptographically secure
- return random.random()
+ return random.random() # $ Alert
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-338/InsecureRandomness.qlref b/python/ql/test/experimental/query-tests/Security/CWE-338/InsecureRandomness.qlref
index 447fc2cf6b2..84cbc2412d9 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-338/InsecureRandomness.qlref
+++ b/python/ql/test/experimental/query-tests/Security/CWE-338/InsecureRandomness.qlref
@@ -1 +1,2 @@
-experimental/Security/CWE-338/InsecureRandomness.ql
\ No newline at end of file
+query: experimental/Security/CWE-338/InsecureRandomness.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-346/Cors.py b/python/ql/test/experimental/query-tests/Security/CWE-346/Cors.py
index cc12e1273fb..e01d99bde75 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-346/Cors.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-346/Cors.py
@@ -4,8 +4,8 @@ def bad():
request = cherrypy.request
validCors = "domain.com"
if request.method in ['POST', 'PUT', 'PATCH', 'DELETE']:
- origin = request.headers.get('Origin', None)
- if origin.startswith(validCors):
+ origin = request.headers.get('Origin', None) # $ Source
+ if origin.startswith(validCors): # $ Alert
print("Origin Valid")
def good():
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-346/CorsBypass.expected b/python/ql/test/experimental/query-tests/Security/CWE-346/CorsBypass.expected
index 32d807c6f6e..5816701791c 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-346/CorsBypass.expected
+++ b/python/ql/test/experimental/query-tests/Security/CWE-346/CorsBypass.expected
@@ -1,3 +1,5 @@
+#select
+| Cors.py:8:12:8:17 | ControlFlowNode for origin | Cors.py:7:18:7:32 | ControlFlowNode for Attribute | Cors.py:8:12:8:17 | ControlFlowNode for origin | Potentially incorrect string comparison which could lead to a CORS bypass. |
edges
| Cors.py:7:9:7:14 | ControlFlowNode for origin | Cors.py:8:12:8:17 | ControlFlowNode for origin | provenance | |
| Cors.py:7:18:7:32 | ControlFlowNode for Attribute | Cors.py:7:18:7:52 | ControlFlowNode for Attribute() | provenance | Config |
@@ -9,5 +11,3 @@ nodes
| Cors.py:7:18:7:52 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| Cors.py:8:12:8:17 | ControlFlowNode for origin | semmle.label | ControlFlowNode for origin |
subpaths
-#select
-| Cors.py:8:12:8:17 | ControlFlowNode for origin | Cors.py:7:18:7:32 | ControlFlowNode for Attribute | Cors.py:8:12:8:17 | ControlFlowNode for origin | Potentially incorrect string comparison which could lead to a CORS bypass. |
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-346/CorsBypass.qlref b/python/ql/test/experimental/query-tests/Security/CWE-346/CorsBypass.qlref
index b652fd93088..35c42c39e85 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-346/CorsBypass.qlref
+++ b/python/ql/test/experimental/query-tests/Security/CWE-346/CorsBypass.qlref
@@ -1 +1,2 @@
-experimental/Security/CWE-346/CorsBypass.ql
\ No newline at end of file
+query: experimental/Security/CWE-346/CorsBypass.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-347/JWTEmptyKeyOrAlgorithm.qlref b/python/ql/test/experimental/query-tests/Security/CWE-347/JWTEmptyKeyOrAlgorithm.qlref
index fe0d2ea0004..d225e37a0d3 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-347/JWTEmptyKeyOrAlgorithm.qlref
+++ b/python/ql/test/experimental/query-tests/Security/CWE-347/JWTEmptyKeyOrAlgorithm.qlref
@@ -1 +1,2 @@
-experimental/Security/CWE-347/JWTEmptyKeyOrAlgorithm.ql
+query: experimental/Security/CWE-347/JWTEmptyKeyOrAlgorithm.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-347/JWTMissingSecretOrPublicKeyVerification.qlref b/python/ql/test/experimental/query-tests/Security/CWE-347/JWTMissingSecretOrPublicKeyVerification.qlref
index d289ff151f4..38402ddd457 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-347/JWTMissingSecretOrPublicKeyVerification.qlref
+++ b/python/ql/test/experimental/query-tests/Security/CWE-347/JWTMissingSecretOrPublicKeyVerification.qlref
@@ -1 +1,2 @@
-experimental/Security/CWE-347/JWTMissingSecretOrPublicKeyVerification.ql
+query: experimental/Security/CWE-347/JWTMissingSecretOrPublicKeyVerification.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-347/authlib.py b/python/ql/test/experimental/query-tests/Security/CWE-347/authlib.py
index 2f736789703..94eb4a38c87 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-347/authlib.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-347/authlib.py
@@ -8,8 +8,8 @@ jwt.encode({"alg": "HS256"}, token, "key")
JsonWebToken().encode({"alg": "HS256"}, token, "key")
# bad - empty key
-jwt.encode({"alg": "HS256"}, token, "")
-JsonWebToken().encode({"alg": "HS256"}, token, "")
+jwt.encode({"alg": "HS256"}, token, "") # $ Alert[py/jwt-empty-secret-or-algorithm]
+JsonWebToken().encode({"alg": "HS256"}, token, "") # $ Alert[py/jwt-empty-secret-or-algorithm]
# Decoding
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-347/pyjwt.py b/python/ql/test/experimental/query-tests/Security/CWE-347/pyjwt.py
index 39892b33dcb..c08375ef9f4 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-347/pyjwt.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-347/pyjwt.py
@@ -7,11 +7,11 @@ jwt.encode(token, "key", "HS256")
jwt.encode(token, key="key", algorithm="HS256")
# bad - both key and algorithm set to None
-jwt.encode(token, None, None)
+jwt.encode(token, None, None) # $ Alert[py/jwt-empty-secret-or-algorithm]
# bad - empty key
-jwt.encode(token, "", algorithm="HS256")
-jwt.encode(token, key="", algorithm="HS256")
+jwt.encode(token, "", algorithm="HS256") # $ Alert[py/jwt-empty-secret-or-algorithm]
+jwt.encode(token, key="", algorithm="HS256") # $ Alert[py/jwt-empty-secret-or-algorithm]
# Decoding
@@ -19,8 +19,8 @@ jwt.encode(token, key="", algorithm="HS256")
jwt.decode(token, "key", "HS256")
# bad - unverified decoding
-jwt.decode(token, verify=False)
-jwt.decode(token, key, options={"verify_signature": False})
+jwt.decode(token, verify=False) # $ Alert[py/jwt-missing-verification]
+jwt.decode(token, key, options={"verify_signature": False}) # $ Alert[py/jwt-missing-verification]
# good - verified decoding
jwt.decode(token, verify=True)
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-347/python_jose.py b/python/ql/test/experimental/query-tests/Security/CWE-347/python_jose.py
index eeb050184d8..8c2bfe90879 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-347/python_jose.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-347/python_jose.py
@@ -7,8 +7,8 @@ jwt.encode(token, "key", "HS256")
jwt.encode(token, key="key", algorithm="HS256")
# bad - empty key
-jwt.encode(token, "", algorithm="HS256")
-jwt.encode(token, key="", algorithm="HS256")
+jwt.encode(token, "", algorithm="HS256") # $ Alert[py/jwt-empty-secret-or-algorithm]
+jwt.encode(token, key="", algorithm="HS256") # $ Alert[py/jwt-empty-secret-or-algorithm]
# Decoding
@@ -16,7 +16,7 @@ jwt.encode(token, key="", algorithm="HS256")
jwt.decode(token, "key", "HS256")
# bad - unverified decoding
-jwt.decode(token, key, options={"verify_signature": False})
+jwt.decode(token, key, options={"verify_signature": False}) # $ Alert[py/jwt-missing-verification]
# good - verified decoding
jwt.decode(token, key, options={"verify_signature": True})
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-347/python_jwt.py b/python/ql/test/experimental/query-tests/Security/CWE-347/python_jwt.py
index 42a3fc35f07..77e67b2dd90 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-347/python_jwt.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-347/python_jwt.py
@@ -11,4 +11,4 @@ def good(token):
def bad(token):
- python_jwt.process_jwt(token)
+ python_jwt.process_jwt(token) # $ Alert[py/jwt-missing-verification]
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.expected b/python/ql/test/experimental/query-tests/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.expected
index 1d529f3b3ea..69e893a6f42 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.expected
+++ b/python/ql/test/experimental/query-tests/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.expected
@@ -1,3 +1,7 @@
+#select
+| flask_bad.py:14:12:14:20 | ControlFlowNode for client_ip | flask_bad.py:13:17:13:54 | ControlFlowNode for Attribute() | flask_bad.py:14:12:14:20 | ControlFlowNode for client_ip | IP address spoofing might include code from $@. | flask_bad.py:13:17:13:54 | ControlFlowNode for Attribute() | this user input |
+| flask_bad.py:21:12:21:20 | ControlFlowNode for client_ip | flask_bad.py:20:17:20:54 | ControlFlowNode for Attribute() | flask_bad.py:21:12:21:20 | ControlFlowNode for client_ip | IP address spoofing might include code from $@. | flask_bad.py:20:17:20:54 | ControlFlowNode for Attribute() | this user input |
+| tornado_bad.py:23:16:23:24 | ControlFlowNode for client_ip | tornado_bad.py:22:25:22:69 | ControlFlowNode for Attribute() | tornado_bad.py:23:16:23:24 | ControlFlowNode for client_ip | IP address spoofing might include code from $@. | tornado_bad.py:22:25:22:69 | ControlFlowNode for Attribute() | this user input |
edges
| flask_bad.py:13:5:13:13 | ControlFlowNode for client_ip | flask_bad.py:14:12:14:20 | ControlFlowNode for client_ip | provenance | |
| flask_bad.py:13:17:13:54 | ControlFlowNode for Attribute() | flask_bad.py:13:5:13:13 | ControlFlowNode for client_ip | provenance | |
@@ -16,7 +20,3 @@ nodes
| tornado_bad.py:22:25:22:69 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| tornado_bad.py:23:16:23:24 | ControlFlowNode for client_ip | semmle.label | ControlFlowNode for client_ip |
subpaths
-#select
-| flask_bad.py:14:12:14:20 | ControlFlowNode for client_ip | flask_bad.py:13:17:13:54 | ControlFlowNode for Attribute() | flask_bad.py:14:12:14:20 | ControlFlowNode for client_ip | IP address spoofing might include code from $@. | flask_bad.py:13:17:13:54 | ControlFlowNode for Attribute() | this user input |
-| flask_bad.py:21:12:21:20 | ControlFlowNode for client_ip | flask_bad.py:20:17:20:54 | ControlFlowNode for Attribute() | flask_bad.py:21:12:21:20 | ControlFlowNode for client_ip | IP address spoofing might include code from $@. | flask_bad.py:20:17:20:54 | ControlFlowNode for Attribute() | this user input |
-| tornado_bad.py:23:16:23:24 | ControlFlowNode for client_ip | tornado_bad.py:22:25:22:69 | ControlFlowNode for Attribute() | tornado_bad.py:23:16:23:24 | ControlFlowNode for client_ip | IP address spoofing might include code from $@. | tornado_bad.py:22:25:22:69 | ControlFlowNode for Attribute() | this user input |
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.qlref b/python/ql/test/experimental/query-tests/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.qlref
index 2a1775fe06a..51f11c6dfcd 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.qlref
+++ b/python/ql/test/experimental/query-tests/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.qlref
@@ -1 +1,2 @@
-experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql
\ No newline at end of file
+query: experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-348/flask_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-348/flask_bad.py
index b357a9316fd..491a1339970 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-348/flask_bad.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-348/flask_bad.py
@@ -10,15 +10,15 @@ app = Flask(__name__)
@app.route('/bad1')
def bad1():
- client_ip = request.headers.get('x-forwarded-for')
- if not client_ip.startswith('192.168.'):
+ client_ip = request.headers.get('x-forwarded-for') # $ Source
+ if not client_ip.startswith('192.168.'): # $ Alert
raise Exception('ip illegal')
return 'bad1'
@app.route('/bad2')
def bad2():
- client_ip = request.headers.get('x-forwarded-for')
- if not client_ip == '127.0.0.1':
+ client_ip = request.headers.get('x-forwarded-for') # $ Source
+ if not client_ip == '127.0.0.1': # $ Alert
raise Exception('ip illegal')
return 'bad2'
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-348/tornado_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-348/tornado_bad.py
index 23ad29d8b09..9899922d019 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-348/tornado_bad.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-348/tornado_bad.py
@@ -19,8 +19,8 @@ class IndexHandler(tornado.web.RequestHandler):
if client_ip:
client_ip = client_ip.split(',')[len(client_ip.split(',')) - 1]
else:
- client_ip = self.request.headers.get('REMOTE_ADDR', None)
- if not client_ip == '127.0.0.1':
+ client_ip = self.request.headers.get('REMOTE_ADDR', None) # $ Source
+ if not client_ip == '127.0.0.1': # $ Alert
raise Exception('ip illegal')
self.write("hello.")
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-522-global-option/LdapInsecureAuth.expected b/python/ql/test/experimental/query-tests/Security/CWE-522-global-option/LdapInsecureAuth.expected
index e217064d1df..58f42bec0c8 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-522-global-option/LdapInsecureAuth.expected
+++ b/python/ql/test/experimental/query-tests/Security/CWE-522-global-option/LdapInsecureAuth.expected
@@ -1,4 +1,4 @@
+#select
edges
nodes
subpaths
-#select
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-522-global-option/LdapInsecureAuth.qlref b/python/ql/test/experimental/query-tests/Security/CWE-522-global-option/LdapInsecureAuth.qlref
index 7b867cb3186..cd63387a1a7 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-522-global-option/LdapInsecureAuth.qlref
+++ b/python/ql/test/experimental/query-tests/Security/CWE-522-global-option/LdapInsecureAuth.qlref
@@ -1 +1,2 @@
-experimental/Security/CWE-522/LdapInsecureAuth.ql
+query: experimental/Security/CWE-522/LdapInsecureAuth.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-522/LdapInsecureAuth.expected b/python/ql/test/experimental/query-tests/Security/CWE-522/LdapInsecureAuth.expected
index b07d47c203c..63a573e7c08 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-522/LdapInsecureAuth.expected
+++ b/python/ql/test/experimental/query-tests/Security/CWE-522/LdapInsecureAuth.expected
@@ -1,3 +1,10 @@
+#select
+| ldap2_remote.py:45:41:45:60 | ControlFlowNode for BinaryExpr | ldap2_remote.py:45:41:45:60 | ControlFlowNode for BinaryExpr | ldap2_remote.py:45:41:45:60 | ControlFlowNode for BinaryExpr | This LDAP host is authenticated insecurely. |
+| ldap2_remote.py:56:41:56:60 | ControlFlowNode for BinaryExpr | ldap2_remote.py:56:41:56:60 | ControlFlowNode for BinaryExpr | ldap2_remote.py:56:41:56:60 | ControlFlowNode for BinaryExpr | This LDAP host is authenticated insecurely. |
+| ldap3_remote.py:102:18:102:21 | ControlFlowNode for host | ldap3_remote.py:101:12:101:49 | ControlFlowNode for BinaryExpr | ldap3_remote.py:102:18:102:21 | ControlFlowNode for host | This LDAP host is authenticated insecurely. |
+| ldap3_remote.py:115:18:115:21 | ControlFlowNode for host | ldap3_remote.py:114:12:114:49 | ControlFlowNode for BinaryExpr | ldap3_remote.py:115:18:115:21 | ControlFlowNode for host | This LDAP host is authenticated insecurely. |
+| ldap3_remote.py:127:18:127:21 | ControlFlowNode for host | ldap3_remote.py:126:12:126:31 | ControlFlowNode for BinaryExpr | ldap3_remote.py:127:18:127:21 | ControlFlowNode for host | This LDAP host is authenticated insecurely. |
+| ldap3_remote.py:139:18:139:21 | ControlFlowNode for host | ldap3_remote.py:2:19:2:25 | ControlFlowNode for ImportMember | ldap3_remote.py:139:18:139:21 | ControlFlowNode for host | This LDAP host is authenticated insecurely. |
edges
| ldap3_remote.py:2:19:2:25 | ControlFlowNode for ImportMember | ldap3_remote.py:2:19:2:25 | ControlFlowNode for request | provenance | |
| ldap3_remote.py:2:19:2:25 | ControlFlowNode for request | ldap3_remote.py:138:21:138:27 | ControlFlowNode for request | provenance | |
@@ -27,10 +34,3 @@ nodes
| ldap3_remote.py:138:21:138:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| ldap3_remote.py:139:18:139:21 | ControlFlowNode for host | semmle.label | ControlFlowNode for host |
subpaths
-#select
-| ldap2_remote.py:45:41:45:60 | ControlFlowNode for BinaryExpr | ldap2_remote.py:45:41:45:60 | ControlFlowNode for BinaryExpr | ldap2_remote.py:45:41:45:60 | ControlFlowNode for BinaryExpr | This LDAP host is authenticated insecurely. |
-| ldap2_remote.py:56:41:56:60 | ControlFlowNode for BinaryExpr | ldap2_remote.py:56:41:56:60 | ControlFlowNode for BinaryExpr | ldap2_remote.py:56:41:56:60 | ControlFlowNode for BinaryExpr | This LDAP host is authenticated insecurely. |
-| ldap3_remote.py:102:18:102:21 | ControlFlowNode for host | ldap3_remote.py:101:12:101:49 | ControlFlowNode for BinaryExpr | ldap3_remote.py:102:18:102:21 | ControlFlowNode for host | This LDAP host is authenticated insecurely. |
-| ldap3_remote.py:115:18:115:21 | ControlFlowNode for host | ldap3_remote.py:114:12:114:49 | ControlFlowNode for BinaryExpr | ldap3_remote.py:115:18:115:21 | ControlFlowNode for host | This LDAP host is authenticated insecurely. |
-| ldap3_remote.py:127:18:127:21 | ControlFlowNode for host | ldap3_remote.py:126:12:126:31 | ControlFlowNode for BinaryExpr | ldap3_remote.py:127:18:127:21 | ControlFlowNode for host | This LDAP host is authenticated insecurely. |
-| ldap3_remote.py:139:18:139:21 | ControlFlowNode for host | ldap3_remote.py:2:19:2:25 | ControlFlowNode for ImportMember | ldap3_remote.py:139:18:139:21 | ControlFlowNode for host | This LDAP host is authenticated insecurely. |
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-522/LdapInsecureAuth.qlref b/python/ql/test/experimental/query-tests/Security/CWE-522/LdapInsecureAuth.qlref
index 7b867cb3186..cd63387a1a7 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-522/LdapInsecureAuth.qlref
+++ b/python/ql/test/experimental/query-tests/Security/CWE-522/LdapInsecureAuth.qlref
@@ -1 +1,2 @@
-experimental/Security/CWE-522/LdapInsecureAuth.ql
+query: experimental/Security/CWE-522/LdapInsecureAuth.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-522/ldap2_remote.py b/python/ql/test/experimental/query-tests/Security/CWE-522/ldap2_remote.py
index 3119ca2d28a..75f5b0b0ea3 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-522/ldap2_remote.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-522/ldap2_remote.py
@@ -42,7 +42,7 @@ def two():
@app.route("/one_bad")
def one_bad():
- ldap_connection_7 = ldap.initialize(schema + remote_host)
+ ldap_connection_7 = ldap.initialize(schema + remote_host) # $ Alert
ldap_connection_7.set_option(ldap.OPT_X_TLS_DEMAND, False)
ldap_connection_7.simple_bind_s('', '')
user = ldap_connection_7.search_s(
@@ -53,7 +53,7 @@ def one_bad():
@app.route("/one_bad_2")
def one_bad_2():
- ldap_connection_8 = ldap.initialize(schema + remote_host)
+ ldap_connection_8 = ldap.initialize(schema + remote_host) # $ Alert
ldap_connection_8.set_option(ldap.OPT_X_TLS_NEVER, True)
ldap_connection_8.simple_bind_s('', '')
user = ldap_connection_8.search_s(
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-522/ldap3_remote.py b/python/ql/test/experimental/query-tests/Security/CWE-522/ldap3_remote.py
index 269e03e41fe..ff5c5998ec2 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-522/ldap3_remote.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-522/ldap3_remote.py
@@ -1,5 +1,5 @@
from ldap3 import Server, Connection, ALL
-from flask import request, Flask
+from flask import request, Flask # $ Source
app = Flask(__name__)
@@ -98,8 +98,8 @@ def seven():
@app.route("/eight")
def eight():
- host = schema + "somethingon.theinternet.com"
- srv = Server(host, port=1337)
+ host = schema + "somethingon.theinternet.com" # $ Source
+ srv = Server(host, port=1337) # $ Alert
conn = Connection(srv, "dn", "password")
conn.start_tls()
conn.search("dn", "search_filter")
@@ -111,8 +111,8 @@ def eight():
@app.route("/nine")
def nine():
- host = schema + "somethingon.theinternet.com"
- srv = Server(host, 1337, False)
+ host = schema + "somethingon.theinternet.com" # $ Source
+ srv = Server(host, 1337, False) # $ Alert
conn = Connection(srv, "dn", "password")
conn.search("dn", "search_filter")
return conn.response
@@ -123,8 +123,8 @@ def nine():
@app.route("/ten")
def ten():
- host = schema + remote_host
- srv = Server(host, port=1337, use_ssl=False)
+ host = schema + remote_host # $ Source
+ srv = Server(host, port=1337, use_ssl=False) # $ Alert
conn = Connection(srv, "dn", "password")
conn.search("dn", "search_filter")
return conn.response
@@ -136,7 +136,7 @@ def ten():
@app.route("/eleven")
def eleven():
host = schema + request.args['host']
- srv = Server(host, port=1337)
+ srv = Server(host, port=1337) # $ Alert
conn = Connection(srv, "dn", "password")
conn.search("dn", "search_filter")
return conn.response
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-611-SimpleXmlRpcServer/SimpleXmlRpcServer.qlref b/python/ql/test/experimental/query-tests/Security/CWE-611-SimpleXmlRpcServer/SimpleXmlRpcServer.qlref
index a0b30e6d69b..f9b2ebd0390 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-611-SimpleXmlRpcServer/SimpleXmlRpcServer.qlref
+++ b/python/ql/test/experimental/query-tests/Security/CWE-611-SimpleXmlRpcServer/SimpleXmlRpcServer.qlref
@@ -1 +1,2 @@
-experimental/Security/CWE-611/SimpleXmlRpcServer.ql
+query: experimental/Security/CWE-611/SimpleXmlRpcServer.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-611-SimpleXmlRpcServer/xmlrpc_server.py b/python/ql/test/experimental/query-tests/Security/CWE-611-SimpleXmlRpcServer/xmlrpc_server.py
index 83c18b549b3..f2463a752bc 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-611-SimpleXmlRpcServer/xmlrpc_server.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-611-SimpleXmlRpcServer/xmlrpc_server.py
@@ -4,7 +4,7 @@ def foo(n: str):
print("foo called with arg:", n, type(n))
return "ok"
-server = SimpleXMLRPCServer(("127.0.0.1", 8000))
+server = SimpleXMLRPCServer(("127.0.0.1", 8000)) # $ Alert
server.register_function(foo, "foo")
server.serve_forever()
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-770/UnicodeDoS.expected b/python/ql/test/experimental/query-tests/Security/CWE-770/UnicodeDoS.expected
index 430e7558fdc..0ef7b8b43b7 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-770/UnicodeDoS.expected
+++ b/python/ql/test/experimental/query-tests/Security/CWE-770/UnicodeDoS.expected
@@ -1,3 +1,10 @@
+#select
+| tests.py:16:39:16:47 | ControlFlowNode for file_path | tests.py:1:35:1:41 | ControlFlowNode for ImportMember | tests.py:16:39:16:47 | ControlFlowNode for file_path | This $@ can reach a $@. | tests.py:1:35:1:41 | ControlFlowNode for ImportMember | user-provided value | tests.py:16:39:16:47 | ControlFlowNode for file_path | costly Unicode normalization operation |
+| tests.py:28:43:28:43 | ControlFlowNode for r | tests.py:1:35:1:41 | ControlFlowNode for ImportMember | tests.py:28:43:28:43 | ControlFlowNode for r | This $@ can reach a $@. | tests.py:1:35:1:41 | ControlFlowNode for ImportMember | user-provided value | tests.py:28:43:28:43 | ControlFlowNode for r | costly Unicode normalization operation |
+| tests.py:40:43:40:43 | ControlFlowNode for r | tests.py:1:35:1:41 | ControlFlowNode for ImportMember | tests.py:40:43:40:43 | ControlFlowNode for r | This $@ can reach a $@. | tests.py:1:35:1:41 | ControlFlowNode for ImportMember | user-provided value | tests.py:40:43:40:43 | ControlFlowNode for r | costly Unicode normalization operation |
+| tests.py:52:43:52:43 | ControlFlowNode for r | tests.py:1:35:1:41 | ControlFlowNode for ImportMember | tests.py:52:43:52:43 | ControlFlowNode for r | This $@ can reach a $@. | tests.py:1:35:1:41 | ControlFlowNode for ImportMember | user-provided value | tests.py:52:43:52:43 | ControlFlowNode for r | costly Unicode normalization operation |
+| tests.py:64:43:64:43 | ControlFlowNode for r | tests.py:1:35:1:41 | ControlFlowNode for ImportMember | tests.py:64:43:64:43 | ControlFlowNode for r | This $@ can reach a $@. | tests.py:1:35:1:41 | ControlFlowNode for ImportMember | user-provided value | tests.py:64:43:64:43 | ControlFlowNode for r | costly Unicode normalization operation |
+| tests.py:76:43:76:43 | ControlFlowNode for r | tests.py:1:35:1:41 | ControlFlowNode for ImportMember | tests.py:76:43:76:43 | ControlFlowNode for r | This $@ can reach a $@. | tests.py:1:35:1:41 | ControlFlowNode for ImportMember | user-provided value | tests.py:76:43:76:43 | ControlFlowNode for r | costly Unicode normalization operation |
edges
| tests.py:1:35:1:41 | ControlFlowNode for ImportMember | tests.py:1:35:1:41 | ControlFlowNode for request | provenance | |
| tests.py:1:35:1:41 | ControlFlowNode for request | tests.py:12:17:12:23 | ControlFlowNode for request | provenance | |
@@ -64,10 +71,3 @@ nodes
| tests.py:72:9:72:33 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| tests.py:76:43:76:43 | ControlFlowNode for r | semmle.label | ControlFlowNode for r |
subpaths
-#select
-| tests.py:16:39:16:47 | ControlFlowNode for file_path | tests.py:1:35:1:41 | ControlFlowNode for ImportMember | tests.py:16:39:16:47 | ControlFlowNode for file_path | This $@ can reach a $@. | tests.py:1:35:1:41 | ControlFlowNode for ImportMember | user-provided value | tests.py:16:39:16:47 | ControlFlowNode for file_path | costly Unicode normalization operation |
-| tests.py:28:43:28:43 | ControlFlowNode for r | tests.py:1:35:1:41 | ControlFlowNode for ImportMember | tests.py:28:43:28:43 | ControlFlowNode for r | This $@ can reach a $@. | tests.py:1:35:1:41 | ControlFlowNode for ImportMember | user-provided value | tests.py:28:43:28:43 | ControlFlowNode for r | costly Unicode normalization operation |
-| tests.py:40:43:40:43 | ControlFlowNode for r | tests.py:1:35:1:41 | ControlFlowNode for ImportMember | tests.py:40:43:40:43 | ControlFlowNode for r | This $@ can reach a $@. | tests.py:1:35:1:41 | ControlFlowNode for ImportMember | user-provided value | tests.py:40:43:40:43 | ControlFlowNode for r | costly Unicode normalization operation |
-| tests.py:52:43:52:43 | ControlFlowNode for r | tests.py:1:35:1:41 | ControlFlowNode for ImportMember | tests.py:52:43:52:43 | ControlFlowNode for r | This $@ can reach a $@. | tests.py:1:35:1:41 | ControlFlowNode for ImportMember | user-provided value | tests.py:52:43:52:43 | ControlFlowNode for r | costly Unicode normalization operation |
-| tests.py:64:43:64:43 | ControlFlowNode for r | tests.py:1:35:1:41 | ControlFlowNode for ImportMember | tests.py:64:43:64:43 | ControlFlowNode for r | This $@ can reach a $@. | tests.py:1:35:1:41 | ControlFlowNode for ImportMember | user-provided value | tests.py:64:43:64:43 | ControlFlowNode for r | costly Unicode normalization operation |
-| tests.py:76:43:76:43 | ControlFlowNode for r | tests.py:1:35:1:41 | ControlFlowNode for ImportMember | tests.py:76:43:76:43 | ControlFlowNode for r | This $@ can reach a $@. | tests.py:1:35:1:41 | ControlFlowNode for ImportMember | user-provided value | tests.py:76:43:76:43 | ControlFlowNode for r | costly Unicode normalization operation |
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-770/UnicodeDoS.qlref b/python/ql/test/experimental/query-tests/Security/CWE-770/UnicodeDoS.qlref
index aff380880ea..1124c168344 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-770/UnicodeDoS.qlref
+++ b/python/ql/test/experimental/query-tests/Security/CWE-770/UnicodeDoS.qlref
@@ -1 +1,2 @@
-experimental/Security/CWE-770/UnicodeDoS.ql
\ No newline at end of file
+query: experimental/Security/CWE-770/UnicodeDoS.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-770/tests.py b/python/ql/test/experimental/query-tests/Security/CWE-770/tests.py
index 1007bcc8985..f359cdaca1c 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-770/tests.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-770/tests.py
@@ -1,4 +1,4 @@
-from flask import Flask, jsonify, request
+from flask import Flask, jsonify, request # $ Source
import unicodedata
app = Flask(__name__)
@@ -13,7 +13,7 @@ def bad_1():
# Normalize the file path using NFKC Unicode normalization
return (
- unicodedata.normalize("NFKC", file_path),
+ unicodedata.normalize("NFKC", file_path), # $ Alert
200,
{"Content-Type": "application/octet-stream"},
)
@@ -25,7 +25,7 @@ def bad_2():
if len(r) >= 10:
# Normalize the r using NFKD Unicode normalization
- r = unicodedata.normalize("NFKD", r)
+ r = unicodedata.normalize("NFKD", r) # $ Alert
return r, 200, {"Content-Type": "application/octet-stream"}
else:
return jsonify({"error": "File not found"}), 404
@@ -37,7 +37,7 @@ def bad_3():
length = len(r)
if length >= 1_000:
# Normalize the r using NFKD Unicode normalization
- r = unicodedata.normalize("NFKD", r)
+ r = unicodedata.normalize("NFKD", r) # $ Alert
return r, 200, {"Content-Type": "application/octet-stream"}
else:
return jsonify({"error": "File not found"}), 404
@@ -49,7 +49,7 @@ def bad_4():
length = len(r)
if 1_000 <= length:
# Normalize the r using NFKD Unicode normalization
- r = unicodedata.normalize("NFKD", r)
+ r = unicodedata.normalize("NFKD", r) # $ Alert
return r, 200, {"Content-Type": "application/octet-stream"}
else:
return jsonify({"error": "File not found"}), 404
@@ -61,7 +61,7 @@ def bad_5():
length = len(r)
if not length < 1_000:
# Normalize the r using NFKD Unicode normalization
- r = unicodedata.normalize("NFKD", r)
+ r = unicodedata.normalize("NFKD", r) # $ Alert
return r, 200, {"Content-Type": "application/octet-stream"}
else:
return jsonify({"error": "File not found"}), 404
@@ -73,7 +73,7 @@ def bad_6():
length = len(r)
if not 1_000 > length:
# Normalize the r using NFKD Unicode normalization
- r = unicodedata.normalize("NFKD", r)
+ r = unicodedata.normalize("NFKD", r) # $ Alert
return r, 200, {"Content-Type": "application/octet-stream"}
else:
return jsonify({"error": "File not found"}), 404
diff --git a/python/ql/test/extractor-tests/overlay/basic-overlay-eval/test.qlref b/python/ql/test/extractor-tests/overlay/basic-overlay-eval/test.qlref
index 961494fbda1..7b04068222b 100644
--- a/python/ql/test/extractor-tests/overlay/basic-overlay-eval/test.qlref
+++ b/python/ql/test/extractor-tests/overlay/basic-overlay-eval/test.qlref
@@ -1 +1 @@
-../basic-full-eval/test.ql
+query: ../basic-full-eval/test.ql
diff --git a/python/ql/test/library-tests/dataflow/coverage-py2/argumentRoutingTest.qlref b/python/ql/test/library-tests/dataflow/coverage-py2/argumentRoutingTest.qlref
index 58bedc4c88c..e555b1a3126 100644
--- a/python/ql/test/library-tests/dataflow/coverage-py2/argumentRoutingTest.qlref
+++ b/python/ql/test/library-tests/dataflow/coverage-py2/argumentRoutingTest.qlref
@@ -1 +1 @@
-../coverage/argumentRoutingTest.ql
+query: ../coverage/argumentRoutingTest.ql
diff --git a/python/ql/test/library-tests/dataflow/coverage-py3/argumentRoutingTest.qlref b/python/ql/test/library-tests/dataflow/coverage-py3/argumentRoutingTest.qlref
index 58bedc4c88c..e555b1a3126 100644
--- a/python/ql/test/library-tests/dataflow/coverage-py3/argumentRoutingTest.qlref
+++ b/python/ql/test/library-tests/dataflow/coverage-py3/argumentRoutingTest.qlref
@@ -1 +1 @@
-../coverage/argumentRoutingTest.ql
+query: ../coverage/argumentRoutingTest.ql
diff --git a/python/ql/test/library-tests/dataflow/typetracking_imports/tracked.qlref b/python/ql/test/library-tests/dataflow/typetracking_imports/tracked.qlref
index 2c005903470..30e4cf2cc46 100644
--- a/python/ql/test/library-tests/dataflow/typetracking_imports/tracked.qlref
+++ b/python/ql/test/library-tests/dataflow/typetracking_imports/tracked.qlref
@@ -1 +1 @@
-../typetracking/tracked.ql
+query: ../typetracking/tracked.ql
diff --git a/python/ql/test/library-tests/frameworks/django-orm/ReflectedXss.qlref b/python/ql/test/library-tests/frameworks/django-orm/ReflectedXss.qlref
index e0efe102416..52f5dddc6c6 100644
--- a/python/ql/test/library-tests/frameworks/django-orm/ReflectedXss.qlref
+++ b/python/ql/test/library-tests/frameworks/django-orm/ReflectedXss.qlref
@@ -1 +1 @@
-Security/CWE-079/ReflectedXss.ql
+query: Security/CWE-079/ReflectedXss.ql
diff --git a/python/ql/test/library-tests/frameworks/gradio/taint_step_test.qlref b/python/ql/test/library-tests/frameworks/gradio/taint_step_test.qlref
index d43482cc509..ee6206aa232 100644
--- a/python/ql/test/library-tests/frameworks/gradio/taint_step_test.qlref
+++ b/python/ql/test/library-tests/frameworks/gradio/taint_step_test.qlref
@@ -1 +1 @@
-Security/CWE-022/PathInjection.ql
+query: Security/CWE-022/PathInjection.ql
diff --git a/python/ql/test/modelling/FrameworkModeEndpoints.qlref b/python/ql/test/modelling/FrameworkModeEndpoints.qlref
index 5ae87455edd..ec216021687 100644
--- a/python/ql/test/modelling/FrameworkModeEndpoints.qlref
+++ b/python/ql/test/modelling/FrameworkModeEndpoints.qlref
@@ -1 +1 @@
-utils/modeleditor/FrameworkModeEndpoints.ql
\ No newline at end of file
+query: utils/modeleditor/FrameworkModeEndpoints.ql
diff --git a/python/ql/test/query-tests/Classes/Arguments/WrongNameForArgumentInClassInstantiation.qlref b/python/ql/test/query-tests/Classes/Arguments/WrongNameForArgumentInClassInstantiation.qlref
index 408766dcbf4..e093d3ebd68 100644
--- a/python/ql/test/query-tests/Classes/Arguments/WrongNameForArgumentInClassInstantiation.qlref
+++ b/python/ql/test/query-tests/Classes/Arguments/WrongNameForArgumentInClassInstantiation.qlref
@@ -1 +1,2 @@
-Classes/WrongNameForArgumentInClassInstantiation.ql
\ No newline at end of file
+query: Classes/WrongNameForArgumentInClassInstantiation.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Classes/Arguments/WrongNumberArgumentsInClassInstantiation.qlref b/python/ql/test/query-tests/Classes/Arguments/WrongNumberArgumentsInClassInstantiation.qlref
index 4fdda20e163..cbf14318e59 100644
--- a/python/ql/test/query-tests/Classes/Arguments/WrongNumberArgumentsInClassInstantiation.qlref
+++ b/python/ql/test/query-tests/Classes/Arguments/WrongNumberArgumentsInClassInstantiation.qlref
@@ -1 +1,2 @@
-Classes/WrongNumberArgumentsInClassInstantiation.ql
\ No newline at end of file
+query: Classes/WrongNumberArgumentsInClassInstantiation.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Classes/Arguments/wrong_arguments.py b/python/ql/test/query-tests/Classes/Arguments/wrong_arguments.py
index 7363fdebef4..5c03d0b0849 100644
--- a/python/ql/test/query-tests/Classes/Arguments/wrong_arguments.py
+++ b/python/ql/test/query-tests/Classes/Arguments/wrong_arguments.py
@@ -34,22 +34,22 @@ class F7(object):
# Too few arguments
-F0()
-F1()
-F2()
-F3()
-F4()
-F5()
-F6(1)
-F7(1,2)
+F0() # $ Alert[py/call/wrong-number-class-arguments]
+F1() # $ Alert[py/call/wrong-number-class-arguments]
+F2() # $ Alert[py/call/wrong-number-class-arguments]
+F3() # $ Alert[py/call/wrong-number-class-arguments]
+F4() # $ Alert[py/call/wrong-number-class-arguments]
+F5() # $ Alert[py/call/wrong-number-class-arguments]
+F6(1) # $ Alert[py/call/wrong-number-class-arguments]
+F7(1,2) # $ Alert[py/call/wrong-number-class-arguments]
#Too many arguments
-F0(1,2)
-F1(1,2,3)
-F5(1,2,3)
-F6(1,2,3)
-F6(1,2,3,4)
+F0(1,2) # $ Alert[py/call/wrong-number-class-arguments]
+F1(1,2,3) # $ Alert[py/call/wrong-number-class-arguments]
+F5(1,2,3) # $ Alert[py/call/wrong-number-class-arguments]
+F6(1,2,3) # $ Alert[py/call/wrong-number-class-arguments]
+F6(1,2,3,4) # $ Alert[py/call/wrong-number-class-arguments]
#OK
@@ -62,9 +62,9 @@ F2(1,2,3,4,5,6)
#Illegal name
-F0(y=1)
-F1(z=1)
-F2(x=0, y=1)
+F0(y=1) # $ Alert[py/call/wrong-named-class-argument]
+F1(z=1) # $ Alert[py/call/wrong-named-class-argument]
+F2(x=0, y=1) # $ Alert[py/call/wrong-named-class-argument]
#Ok name
@@ -82,12 +82,12 @@ t3 = (1,2,3)
f(*t2)
#Too many
-F6(*(1,2,3))
-F6(*t3)
+F6(*(1,2,3)) # $ Alert[py/call/wrong-number-class-arguments]
+F6(*t3) # $ Alert[py/call/wrong-number-class-arguments]
#Ok
F6(**{'x':1, 'y':2})
#Illegal name
-F6(**{'x':1, 'y':2, 'z':3})
+F6(**{'x':1, 'y':2, 'z':3}) # $ Alert[py/call/wrong-named-class-argument]
diff --git a/python/ql/test/query-tests/Classes/conflicting/ConflictingAttributesInBaseClasses.qlref b/python/ql/test/query-tests/Classes/conflicting/ConflictingAttributesInBaseClasses.qlref
index 3d6fa6534c5..efd0250ca2e 100644
--- a/python/ql/test/query-tests/Classes/conflicting/ConflictingAttributesInBaseClasses.qlref
+++ b/python/ql/test/query-tests/Classes/conflicting/ConflictingAttributesInBaseClasses.qlref
@@ -1 +1,2 @@
-Classes/ConflictingAttributesInBaseClasses.ql
\ No newline at end of file
+query: Classes/ConflictingAttributesInBaseClasses.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Classes/conflicting/test.py b/python/ql/test/query-tests/Classes/conflicting/test.py
index 624cea77ce5..4bb75114034 100644
--- a/python/ql/test/query-tests/Classes/conflicting/test.py
+++ b/python/ql/test/query-tests/Classes/conflicting/test.py
@@ -23,7 +23,7 @@ class CB2(Common):
return 0
-class Conflict(CB1, CB2):
+class Conflict(CB1, CB2): # $ Alert
pass
class Override1(Common):
diff --git a/python/ql/test/query-tests/Classes/descriptors/MutatingDescriptor.qlref b/python/ql/test/query-tests/Classes/descriptors/MutatingDescriptor.qlref
index 08449405ad6..17ec44acc88 100644
--- a/python/ql/test/query-tests/Classes/descriptors/MutatingDescriptor.qlref
+++ b/python/ql/test/query-tests/Classes/descriptors/MutatingDescriptor.qlref
@@ -1 +1,2 @@
-Classes/MutatingDescriptor.ql
+query: Classes/MutatingDescriptor.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Classes/descriptors/test.py b/python/ql/test/query-tests/Classes/descriptors/test.py
index 180ade50e36..b33ae25440f 100644
--- a/python/ql/test/query-tests/Classes/descriptors/test.py
+++ b/python/ql/test/query-tests/Classes/descriptors/test.py
@@ -7,7 +7,7 @@ class MutatingDescriptor(object):
def __get__(self, obj, obj_type):
#Modified state is visible to all instances.
- self.my_obj = obj
+ self.my_obj = obj # $ Alert
return self
def __call__(self, *args):
@@ -22,4 +22,4 @@ class MutatingDescriptor(object):
def not_ok(self, value):
#Modified state is visible to all instances.
- self.my_obj = value
+ self.my_obj = value # $ Alert
diff --git a/python/ql/test/query-tests/Classes/equals-attr/DefineEqualsWhenAddingAttributes.qlref b/python/ql/test/query-tests/Classes/equals-attr/DefineEqualsWhenAddingAttributes.qlref
index e542a6176ad..f3385f506bf 100644
--- a/python/ql/test/query-tests/Classes/equals-attr/DefineEqualsWhenAddingAttributes.qlref
+++ b/python/ql/test/query-tests/Classes/equals-attr/DefineEqualsWhenAddingAttributes.qlref
@@ -1 +1,2 @@
-Classes/DefineEqualsWhenAddingAttributes.ql
\ No newline at end of file
+query: Classes/DefineEqualsWhenAddingAttributes.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Classes/equals-attr/attr_eq_test.py b/python/ql/test/query-tests/Classes/equals-attr/attr_eq_test.py
index e1e545fe9ef..a5b1857f878 100644
--- a/python/ql/test/query-tests/Classes/equals-attr/attr_eq_test.py
+++ b/python/ql/test/query-tests/Classes/equals-attr/attr_eq_test.py
@@ -18,7 +18,7 @@ class Point(object):
def __hash__(self):
return hash((self._x, self._y))
-class BadColorPoint(Point):
+class BadColorPoint(Point): # $ Alert
def __init__(self, x, y, color):
Point.__init__(self, x, y)
diff --git a/python/ql/test/query-tests/Classes/init-calls-subclass-method/InitCallsSubclassMethod.qlref b/python/ql/test/query-tests/Classes/init-calls-subclass-method/InitCallsSubclassMethod.qlref
index 6530409f90a..c396a4dbc3d 100644
--- a/python/ql/test/query-tests/Classes/init-calls-subclass-method/InitCallsSubclassMethod.qlref
+++ b/python/ql/test/query-tests/Classes/init-calls-subclass-method/InitCallsSubclassMethod.qlref
@@ -1 +1,2 @@
-Classes/InitCallsSubclass/InitCallsSubclassMethod.ql
+query: Classes/InitCallsSubclass/InitCallsSubclassMethod.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Classes/init-calls-subclass-method/init_calls_subclass.py b/python/ql/test/query-tests/Classes/init-calls-subclass-method/init_calls_subclass.py
index ef944a9c7ef..22f6707a4c9 100644
--- a/python/ql/test/query-tests/Classes/init-calls-subclass-method/init_calls_subclass.py
+++ b/python/ql/test/query-tests/Classes/init-calls-subclass-method/init_calls_subclass.py
@@ -5,7 +5,7 @@ def bad1():
def __init__(self, arg):
self._state = "Not OK"
- self.set_up(arg) # BAD: set_up is overriden.
+ self.set_up(arg) # BAD: set_up is overriden. # $ Alert
self._state = "OK"
def set_up(self, arg):
@@ -29,7 +29,7 @@ def bad2():
self.a = arg
# BAD: postproc is called after initialization. This is still an issue
# since it may still occur before all initialization on a subclass is complete.
- self.postproc()
+ self.postproc() # $ Alert
def postproc(self):
if self.a == 1:
diff --git a/python/ql/test/query-tests/Classes/overwriting-attribute/OverwritingAttributeInSuperClass.qlref b/python/ql/test/query-tests/Classes/overwriting-attribute/OverwritingAttributeInSuperClass.qlref
index b29c4d25025..dcea036ee60 100644
--- a/python/ql/test/query-tests/Classes/overwriting-attribute/OverwritingAttributeInSuperClass.qlref
+++ b/python/ql/test/query-tests/Classes/overwriting-attribute/OverwritingAttributeInSuperClass.qlref
@@ -1 +1,2 @@
-Classes/OverwritingAttributeInSuperClass.ql
+query: Classes/OverwritingAttributeInSuperClass.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Classes/overwriting-attribute/overwriting_attribute.py b/python/ql/test/query-tests/Classes/overwriting-attribute/overwriting_attribute.py
index 0372db0b215..a17bfd662d8 100644
--- a/python/ql/test/query-tests/Classes/overwriting-attribute/overwriting_attribute.py
+++ b/python/ql/test/query-tests/Classes/overwriting-attribute/overwriting_attribute.py
@@ -2,7 +2,7 @@
class C(object):
def __init__(self):
- self.var = 0
+ self.var = 0 # $ Alert
class D(C):
@@ -20,4 +20,4 @@ class F(E):
def __init__(self):
E.__init__(self)
- self.var = 1
+ self.var = 1 # $ Alert
diff --git a/python/ql/test/query-tests/Classes/should-be-context-manager/ShouldBeContextManager.qlref b/python/ql/test/query-tests/Classes/should-be-context-manager/ShouldBeContextManager.qlref
index f555b0af07a..b13b7d8b7b9 100644
--- a/python/ql/test/query-tests/Classes/should-be-context-manager/ShouldBeContextManager.qlref
+++ b/python/ql/test/query-tests/Classes/should-be-context-manager/ShouldBeContextManager.qlref
@@ -1 +1,2 @@
-Classes/ShouldBeContextManager.ql
\ No newline at end of file
+query: Classes/ShouldBeContextManager.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Classes/should-be-context-manager/should_be_context_manager.py b/python/ql/test/query-tests/Classes/should-be-context-manager/should_be_context_manager.py
index 68fc81206a3..869d19f3d86 100644
--- a/python/ql/test/query-tests/Classes/should-be-context-manager/should_be_context_manager.py
+++ b/python/ql/test/query-tests/Classes/should-be-context-manager/should_be_context_manager.py
@@ -1,6 +1,6 @@
#Should be context manager
-class MegaDel(object):
+class MegaDel(object): # $ Alert
def __del__(self):
a = self.x + self.y
@@ -13,7 +13,7 @@ class MegaDel(object):
sum += a
print(sum)
-class MiniDel(object):
+class MiniDel(object): # $ Alert
def close(self):
pass
diff --git a/python/ql/test/query-tests/Classes/undefined-attribute/MaybeUndefinedClassAttribute.qlref b/python/ql/test/query-tests/Classes/undefined-attribute/MaybeUndefinedClassAttribute.qlref
index d4986ffc84c..35f6da7add5 100644
--- a/python/ql/test/query-tests/Classes/undefined-attribute/MaybeUndefinedClassAttribute.qlref
+++ b/python/ql/test/query-tests/Classes/undefined-attribute/MaybeUndefinedClassAttribute.qlref
@@ -1 +1,2 @@
-Classes/MaybeUndefinedClassAttribute.ql
+query: Classes/MaybeUndefinedClassAttribute.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Classes/undefined-attribute/UndefinedClassAttribute.qlref b/python/ql/test/query-tests/Classes/undefined-attribute/UndefinedClassAttribute.qlref
index 7ac0a3b18b7..f0e8fb72278 100644
--- a/python/ql/test/query-tests/Classes/undefined-attribute/UndefinedClassAttribute.qlref
+++ b/python/ql/test/query-tests/Classes/undefined-attribute/UndefinedClassAttribute.qlref
@@ -1 +1,2 @@
-Classes/UndefinedClassAttribute.ql
+query: Classes/UndefinedClassAttribute.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Classes/undefined-attribute/undefined_attribute.py b/python/ql/test/query-tests/Classes/undefined-attribute/undefined_attribute.py
index 0eec9974ef1..207e8f837d6 100644
--- a/python/ql/test/query-tests/Classes/undefined-attribute/undefined_attribute.py
+++ b/python/ql/test/query-tests/Classes/undefined-attribute/undefined_attribute.py
@@ -21,10 +21,10 @@ class Attributes(object):
print (self.local_exists)
def neca1(self):
- print (self.not_exists)
+ print (self.not_exists) # $ Alert[py/undefined-attribute]
def neca2(self):
- print (self.may_exist)
+ print (self.may_exist) # $ Alert[py/maybe-undefined-attribute]
#This is OK
class SetViaDict(object):
@@ -106,7 +106,7 @@ class DecoratedInit(object):
class NoInit(object):
def use_y(self):
- return self.y
+ return self.y # $ Alert[py/undefined-attribute]
#This is also OK
class SetLocally2(object):
@@ -181,7 +181,7 @@ class Test1(object):
self.return_queue = frame.method.queue
def use_it(self):
- return self.return_queue
+ return self.return_queue # $ Alert[py/maybe-undefined-attribute]
#Check for FPs when overriding builtin methods
@@ -247,15 +247,15 @@ class Customer1(object):
class Odasa4619a(object):
def call(self):
- host = self.glance_host
- port = self.glance_port
+ host = self.glance_host # $ Alert[py/undefined-attribute]
+ port = self.glance_port # $ Alert[py/undefined-attribute]
class Odasa4619b(object):
def call(self):
- host = self.glance_host
- port = self.glance_port
+ host = self.glance_host # $ Alert[py/maybe-undefined-attribute]
+ port = self.glance_port # $ Alert[py/maybe-undefined-attribute]
@decorator
def foo(self):
diff --git a/python/ql/test/query-tests/Classes/useless/UselessClass.qlref b/python/ql/test/query-tests/Classes/useless/UselessClass.qlref
index 9c8e87e962c..6dac346e62b 100644
--- a/python/ql/test/query-tests/Classes/useless/UselessClass.qlref
+++ b/python/ql/test/query-tests/Classes/useless/UselessClass.qlref
@@ -1 +1,2 @@
-Classes/UselessClass.ql
+query: Classes/UselessClass.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Classes/useless/test.py b/python/ql/test/query-tests/Classes/useless/test.py
index 40c9e56e117..063da81c172 100644
--- a/python/ql/test/query-tests/Classes/useless/test.py
+++ b/python/ql/test/query-tests/Classes/useless/test.py
@@ -25,7 +25,7 @@ class Useful2(object):
pass
-class Useless1(object):
+class Useless1(object): # $ Alert
def __init__(self):
pass
@@ -34,7 +34,7 @@ class Useless1(object):
pass
-class Useless2(object):
+class Useless2(object): # $ Alert
def do_something(self):
pass
diff --git a/python/ql/test/query-tests/Diagnostics/ExtractedFiles.qlref b/python/ql/test/query-tests/Diagnostics/ExtractedFiles.qlref
index e900e9c5314..58bc903a431 100644
--- a/python/ql/test/query-tests/Diagnostics/ExtractedFiles.qlref
+++ b/python/ql/test/query-tests/Diagnostics/ExtractedFiles.qlref
@@ -1 +1 @@
-Diagnostics/ExtractedFiles.ql
+query: Diagnostics/ExtractedFiles.ql
diff --git a/python/ql/test/query-tests/Diagnostics/ExtractionWarnings.qlref b/python/ql/test/query-tests/Diagnostics/ExtractionWarnings.qlref
index 2df3d933e8a..68969e9bbf1 100644
--- a/python/ql/test/query-tests/Diagnostics/ExtractionWarnings.qlref
+++ b/python/ql/test/query-tests/Diagnostics/ExtractionWarnings.qlref
@@ -1 +1 @@
-Diagnostics/ExtractionWarnings.ql
+query: Diagnostics/ExtractionWarnings.ql
diff --git a/python/ql/test/query-tests/Exceptions/general/CatchingBaseException.qlref b/python/ql/test/query-tests/Exceptions/general/CatchingBaseException.qlref
index 5588dbf2c7b..bd98ca75af1 100644
--- a/python/ql/test/query-tests/Exceptions/general/CatchingBaseException.qlref
+++ b/python/ql/test/query-tests/Exceptions/general/CatchingBaseException.qlref
@@ -1 +1 @@
-Exceptions/CatchingBaseException.ql
\ No newline at end of file
+query: Exceptions/CatchingBaseException.ql
diff --git a/python/ql/test/query-tests/Exceptions/general/EmptyExcept.qlref b/python/ql/test/query-tests/Exceptions/general/EmptyExcept.qlref
index 3f4987046b1..16e16f16ba5 100644
--- a/python/ql/test/query-tests/Exceptions/general/EmptyExcept.qlref
+++ b/python/ql/test/query-tests/Exceptions/general/EmptyExcept.qlref
@@ -1 +1 @@
-Exceptions/EmptyExcept.ql
\ No newline at end of file
+query: Exceptions/EmptyExcept.ql
diff --git a/python/ql/test/query-tests/Exceptions/general/IllegalExceptionHandlerType.qlref b/python/ql/test/query-tests/Exceptions/general/IllegalExceptionHandlerType.qlref
index 6d49710a759..4e3f71fe812 100644
--- a/python/ql/test/query-tests/Exceptions/general/IllegalExceptionHandlerType.qlref
+++ b/python/ql/test/query-tests/Exceptions/general/IllegalExceptionHandlerType.qlref
@@ -1 +1 @@
-Exceptions/IllegalExceptionHandlerType.ql
\ No newline at end of file
+query: Exceptions/IllegalExceptionHandlerType.ql
diff --git a/python/ql/test/query-tests/Exceptions/general/IllegalRaise.qlref b/python/ql/test/query-tests/Exceptions/general/IllegalRaise.qlref
index 5a515d5656d..95e65710025 100644
--- a/python/ql/test/query-tests/Exceptions/general/IllegalRaise.qlref
+++ b/python/ql/test/query-tests/Exceptions/general/IllegalRaise.qlref
@@ -1 +1 @@
-Exceptions/IllegalRaise.ql
\ No newline at end of file
+query: Exceptions/IllegalRaise.ql
diff --git a/python/ql/test/query-tests/Exceptions/general/NotImplementedIsNotAnException.qlref b/python/ql/test/query-tests/Exceptions/general/NotImplementedIsNotAnException.qlref
index 61ac527ffb9..5b199983f75 100644
--- a/python/ql/test/query-tests/Exceptions/general/NotImplementedIsNotAnException.qlref
+++ b/python/ql/test/query-tests/Exceptions/general/NotImplementedIsNotAnException.qlref
@@ -1 +1 @@
-Exceptions/NotImplementedIsNotAnException.ql
\ No newline at end of file
+query: Exceptions/NotImplementedIsNotAnException.ql
diff --git a/python/ql/test/query-tests/Expressions/Arguments/WrongNameForArgumentInCall.qlref b/python/ql/test/query-tests/Expressions/Arguments/WrongNameForArgumentInCall.qlref
index 3599f204f55..c6b6ca3d30f 100644
--- a/python/ql/test/query-tests/Expressions/Arguments/WrongNameForArgumentInCall.qlref
+++ b/python/ql/test/query-tests/Expressions/Arguments/WrongNameForArgumentInCall.qlref
@@ -1 +1,2 @@
-Expressions/WrongNameForArgumentInCall.ql
\ No newline at end of file
+query: Expressions/WrongNameForArgumentInCall.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Expressions/Arguments/WrongNumberArgumentsInCall.qlref b/python/ql/test/query-tests/Expressions/Arguments/WrongNumberArgumentsInCall.qlref
index 1bffe8f1cad..68dc510d5c6 100644
--- a/python/ql/test/query-tests/Expressions/Arguments/WrongNumberArgumentsInCall.qlref
+++ b/python/ql/test/query-tests/Expressions/Arguments/WrongNumberArgumentsInCall.qlref
@@ -1 +1,2 @@
-Expressions/WrongNumberArgumentsInCall.ql
\ No newline at end of file
+query: Expressions/WrongNumberArgumentsInCall.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Expressions/Arguments/use_mox.py b/python/ql/test/query-tests/Expressions/Arguments/use_mox.py
index 35d35574895..0af38ad3798 100644
--- a/python/ql/test/query-tests/Expressions/Arguments/use_mox.py
+++ b/python/ql/test/query-tests/Expressions/Arguments/use_mox.py
@@ -25,9 +25,9 @@ C.m1(1,2)
#But normal functions are treated normally
-f0()
-f1(1)
+f0() # $ Alert[py/call/wrong-arguments]
+f1(1) # $ Alert[py/call/wrong-arguments]
#As are normal methods
-C().m0()
-C().m1(1)
+C().m0() # $ Alert[py/call/wrong-arguments]
+C().m1(1) # $ Alert[py/call/wrong-arguments]
diff --git a/python/ql/test/query-tests/Expressions/Arguments/wrong_arguments.py b/python/ql/test/query-tests/Expressions/Arguments/wrong_arguments.py
index 284d1d19bc3..dffafbeee76 100644
--- a/python/ql/test/query-tests/Expressions/Arguments/wrong_arguments.py
+++ b/python/ql/test/query-tests/Expressions/Arguments/wrong_arguments.py
@@ -26,22 +26,22 @@ def f7(x, y, z):
# Too few arguments
-f0()
-f1()
-f2()
-f3()
-f4()
-f5()
-f6(1)
-f7(1,2)
+f0() # $ Alert[py/call/wrong-arguments]
+f1() # $ Alert[py/call/wrong-arguments]
+f2() # $ Alert[py/call/wrong-arguments]
+f3() # $ Alert[py/call/wrong-arguments]
+f4() # $ Alert[py/call/wrong-arguments]
+f5() # $ Alert[py/call/wrong-arguments]
+f6(1) # $ Alert[py/call/wrong-arguments]
+f7(1,2) # $ Alert[py/call/wrong-arguments]
#Too many arguments
-f0(1,2)
-f1(1,2,3)
-f5(1,2,3)
-f6(1,2,3)
-f6(1,2,3,4)
+f0(1,2) # $ Alert[py/call/wrong-arguments]
+f1(1,2,3) # $ Alert[py/call/wrong-arguments]
+f5(1,2,3) # $ Alert[py/call/wrong-arguments]
+f6(1,2,3) # $ Alert[py/call/wrong-arguments]
+f6(1,2,3,4) # $ Alert[py/call/wrong-arguments]
#OK
@@ -54,9 +54,9 @@ f2(1,2,3,4,5,6)
#Illegal name
-f0(y=1)
-f1(z=1)
-f2(x=0, y=1)
+f0(y=1) # $ Alert[py/call/wrong-named-argument]
+f1(z=1) # $ Alert[py/call/wrong-named-argument]
+f2(x=0, y=1) # $ Alert[py/call/wrong-named-argument]
#Ok name
@@ -78,12 +78,12 @@ l1d()
l1d(1)
#Too many
-l0(1)
-l1(1,2)
-l1d(1,2)
+l0(1) # $ Alert[py/call/wrong-arguments]
+l1(1,2) # $ Alert[py/call/wrong-arguments]
+l1d(1,2) # $ Alert[py/call/wrong-arguments]
#Too few
-l1()
+l1() # $ Alert[py/call/wrong-arguments]
t2 = (1,2)
@@ -93,14 +93,14 @@ t3 = (1,2,3)
f(*t2)
#Too many
-f6(*(1,2,3))
-f6(*t3)
+f6(*(1,2,3)) # $ Alert[py/call/wrong-arguments]
+f6(*t3) # $ Alert[py/call/wrong-arguments]
#Ok
f6(**{'x':1, 'y':2})
#Illegal name
-f6(**{'x':1, 'y':2, 'z':3})
+f6(**{'x':1, 'y':2, 'z':3}) # $ Alert[py/call/wrong-named-argument]
#Theoretically -1 arguments required. Don't report
class C(object):
@@ -112,7 +112,7 @@ C().f()
#Too many and wrong name -- check only wrong name is flagged.
-f1(x, y, z=1)
+f1(x, y, z=1) # $ Alert[py/call/wrong-named-argument]
#Overriding and call is wrong.
@@ -127,5 +127,5 @@ class Eggs2(Eggs1):
pass
e = Eggs1() if cond else Eggs2()
-e.spam(0)
+e.spam(0) # $ Alert[py/call/wrong-arguments]
diff --git a/python/ql/test/query-tests/Expressions/Formatting/MixedExplicitImplicitIn3101Format.qlref b/python/ql/test/query-tests/Expressions/Formatting/MixedExplicitImplicitIn3101Format.qlref
index 3b9a8dc0ccf..044e500615f 100644
--- a/python/ql/test/query-tests/Expressions/Formatting/MixedExplicitImplicitIn3101Format.qlref
+++ b/python/ql/test/query-tests/Expressions/Formatting/MixedExplicitImplicitIn3101Format.qlref
@@ -1 +1,2 @@
-Expressions/Formatting/MixedExplicitImplicitIn3101Format.ql
\ No newline at end of file
+query: Expressions/Formatting/MixedExplicitImplicitIn3101Format.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Expressions/Formatting/UnusedArgumentIn3101Format.qlref b/python/ql/test/query-tests/Expressions/Formatting/UnusedArgumentIn3101Format.qlref
index b3e654ad052..8de137448b6 100644
--- a/python/ql/test/query-tests/Expressions/Formatting/UnusedArgumentIn3101Format.qlref
+++ b/python/ql/test/query-tests/Expressions/Formatting/UnusedArgumentIn3101Format.qlref
@@ -1 +1,2 @@
-Expressions/Formatting/UnusedArgumentIn3101Format.ql
\ No newline at end of file
+query: Expressions/Formatting/UnusedArgumentIn3101Format.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Expressions/Formatting/UnusedNamedArgumentIn3101Format.qlref b/python/ql/test/query-tests/Expressions/Formatting/UnusedNamedArgumentIn3101Format.qlref
index 6a77d891079..a1e71b6cd8b 100644
--- a/python/ql/test/query-tests/Expressions/Formatting/UnusedNamedArgumentIn3101Format.qlref
+++ b/python/ql/test/query-tests/Expressions/Formatting/UnusedNamedArgumentIn3101Format.qlref
@@ -1 +1,2 @@
-Expressions/Formatting/UnusedNamedArgumentIn3101Format.ql
\ No newline at end of file
+query: Expressions/Formatting/UnusedNamedArgumentIn3101Format.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Expressions/Formatting/WrongNameInArgumentsFor3101Format.qlref b/python/ql/test/query-tests/Expressions/Formatting/WrongNameInArgumentsFor3101Format.qlref
index e0b30887034..6bd5b9c75da 100644
--- a/python/ql/test/query-tests/Expressions/Formatting/WrongNameInArgumentsFor3101Format.qlref
+++ b/python/ql/test/query-tests/Expressions/Formatting/WrongNameInArgumentsFor3101Format.qlref
@@ -1 +1,2 @@
-Expressions/Formatting/WrongNameInArgumentsFor3101Format.ql
\ No newline at end of file
+query: Expressions/Formatting/WrongNameInArgumentsFor3101Format.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Expressions/Formatting/WrongNumberArgumentsFor3101Format.qlref b/python/ql/test/query-tests/Expressions/Formatting/WrongNumberArgumentsFor3101Format.qlref
index 130a6525a90..02168e01c64 100644
--- a/python/ql/test/query-tests/Expressions/Formatting/WrongNumberArgumentsFor3101Format.qlref
+++ b/python/ql/test/query-tests/Expressions/Formatting/WrongNumberArgumentsFor3101Format.qlref
@@ -1 +1,2 @@
-Expressions/Formatting/WrongNumberArgumentsFor3101Format.ql
\ No newline at end of file
+query: Expressions/Formatting/WrongNumberArgumentsFor3101Format.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Expressions/Formatting/test.py b/python/ql/test/query-tests/Expressions/Formatting/test.py
index e9fd23c8aad..3117a9de2a4 100755
--- a/python/ql/test/query-tests/Expressions/Formatting/test.py
+++ b/python/ql/test/query-tests/Expressions/Formatting/test.py
@@ -1,11 +1,11 @@
from __future__ import unicode_literals
-mixed_format1 = "{}{1}"
+mixed_format1 = "{}{1}" # $ Alert[py/str-format/mixed-fields]
named_format1 = "{name!r}, {0}"
explicit_format1 = "{0}, {1}"
implicit_format1 = "{}, {}"
-mixed_format2 = "{}{1}"
+mixed_format2 = "{}{1}" # $ Alert[py/str-format/mixed-fields]
named_format2 = "{name!r}, {0}"
explicit_format2 = "{0}, {1}"
implicit_format2 = "{}, {}"
@@ -14,23 +14,23 @@ implicit_format2 = "{}, {}"
mixed_format1.format("Hello", "World")
format(mixed_format2, "Hello", "World")
-named_format1.format("Hello", world="World")
-format(named_format2, "Hello", world="World")
+named_format1.format("Hello", world="World") # $ Alert[py/str-format/missing-named-argument] Alert[py/str-format/surplus-named-argument]
+format(named_format2, "Hello", world="World") # $ Alert[py/str-format/missing-named-argument] Alert[py/str-format/surplus-named-argument]
-named_format1.format(name="Hello", world="World")
-format(named_format2, name="Hello", world="World")
+named_format1.format(name="Hello", world="World") # $ Alert[py/str-format/missing-argument] Alert[py/str-format/surplus-named-argument]
+format(named_format2, name="Hello", world="World") # $ Alert[py/str-format/missing-argument] Alert[py/str-format/surplus-named-argument]
-explicit_format1.format("Hello")
-format(explicit_format2, "Hello")
+explicit_format1.format("Hello") # $ Alert[py/str-format/missing-argument]
+format(explicit_format2, "Hello") # $ Alert[py/str-format/missing-argument]
-implicit_format1.format("Hello")
-format(implicit_format2, "Hello")
+implicit_format1.format("Hello") # $ Alert[py/str-format/missing-argument]
+format(implicit_format2, "Hello") # $ Alert[py/str-format/missing-argument]
-explicit_format1.format("Hello", "World", "Extra")
-format(explicit_format2, "Hello", "World", "Extra")
+explicit_format1.format("Hello", "World", "Extra") # $ Alert[py/str-format/surplus-argument]
+format(explicit_format2, "Hello", "World", "Extra") # $ Alert[py/str-format/surplus-argument]
-implicit_format1.format("Hello", "World", "Extra")
-format(implicit_format2, "Hello", "World", "Extra")
+implicit_format1.format("Hello", "World", "Extra") # $ Alert[py/str-format/surplus-argument]
+format(implicit_format2, "Hello", "World", "Extra") # $ Alert[py/str-format/surplus-argument]
#OK ODASA-3197
if cond:
@@ -42,8 +42,8 @@ format(x_or_y, x="x", y="y")
x_or_y.format(x="x", y="y")
#Still fail for multiple formats
-format(x_or_y, x="x", y="y", z="z")
-x_or_y.format(x="x", y="y", z="z")
+format(x_or_y, x="x", y="y", z="z") # $ Alert[py/str-format/surplus-named-argument]
+x_or_y.format(x="x", y="y", z="z") # $ Alert[py/str-format/surplus-named-argument]
#False positive reported by customer. -- Verify fix.
"
{{}}> | ".format(html_class)
diff --git a/python/ql/test/query-tests/Expressions/Formatting/unknown_format_string.py b/python/ql/test/query-tests/Expressions/Formatting/unknown_format_string.py
index a3b32a504db..690716e20b2 100644
--- a/python/ql/test/query-tests/Expressions/Formatting/unknown_format_string.py
+++ b/python/ql/test/query-tests/Expressions/Formatting/unknown_format_string.py
@@ -6,7 +6,7 @@ def possibly_unknown_format_string1(x):
fmt = user_specified
else:
fmt = "{a}"
- return fmt.format(a=1,b=2)
+ return fmt.format(a=1,b=2) # $ Alert[py/str-format/surplus-named-argument]
def possibly_unknown_format_string2(x):
user_specified = input()
@@ -14,7 +14,7 @@ def possibly_unknown_format_string2(x):
fmt = user_specified
else:
fmt = "{a}"
- return fmt.format(a=1,b=2)
+ return fmt.format(a=1,b=2) # $ Alert[py/str-format/surplus-named-argument]
def possibly_unknown_format_string3(x):
@@ -22,4 +22,4 @@ def possibly_unknown_format_string3(x):
fmt = input()
else:
fmt = "{a}"
- return fmt.format(a=1,b=2)
+ return fmt.format(a=1,b=2) # $ Alert[py/str-format/surplus-named-argument]
diff --git a/python/ql/test/query-tests/Expressions/Regex/BackspaceEscape.qlref b/python/ql/test/query-tests/Expressions/Regex/BackspaceEscape.qlref
index 2bf85f8a45a..25a46ec7b29 100644
--- a/python/ql/test/query-tests/Expressions/Regex/BackspaceEscape.qlref
+++ b/python/ql/test/query-tests/Expressions/Regex/BackspaceEscape.qlref
@@ -1 +1,2 @@
-Expressions/Regex/BackspaceEscape.ql
+query: Expressions/Regex/BackspaceEscape.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Expressions/Regex/DuplicateCharacterInSet.qlref b/python/ql/test/query-tests/Expressions/Regex/DuplicateCharacterInSet.qlref
index f0fc83c214e..358d546ce8a 100644
--- a/python/ql/test/query-tests/Expressions/Regex/DuplicateCharacterInSet.qlref
+++ b/python/ql/test/query-tests/Expressions/Regex/DuplicateCharacterInSet.qlref
@@ -1 +1,2 @@
-Expressions/Regex/DuplicateCharacterInSet.ql
+query: Expressions/Regex/DuplicateCharacterInSet.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Expressions/Regex/MissingPartSpecialGroup.qlref b/python/ql/test/query-tests/Expressions/Regex/MissingPartSpecialGroup.qlref
index faf8f31ad4d..215e7874972 100644
--- a/python/ql/test/query-tests/Expressions/Regex/MissingPartSpecialGroup.qlref
+++ b/python/ql/test/query-tests/Expressions/Regex/MissingPartSpecialGroup.qlref
@@ -1 +1,2 @@
-Expressions/Regex/MissingPartSpecialGroup.ql
+query: Expressions/Regex/MissingPartSpecialGroup.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Expressions/Regex/UnmatchableCaret.qlref b/python/ql/test/query-tests/Expressions/Regex/UnmatchableCaret.qlref
index 161fd59f7f2..218dcb02198 100644
--- a/python/ql/test/query-tests/Expressions/Regex/UnmatchableCaret.qlref
+++ b/python/ql/test/query-tests/Expressions/Regex/UnmatchableCaret.qlref
@@ -1 +1,2 @@
-Expressions/Regex/UnmatchableCaret.ql
+query: Expressions/Regex/UnmatchableCaret.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Expressions/Regex/UnmatchableDollar.qlref b/python/ql/test/query-tests/Expressions/Regex/UnmatchableDollar.qlref
index b162342922c..cabb436241c 100644
--- a/python/ql/test/query-tests/Expressions/Regex/UnmatchableDollar.qlref
+++ b/python/ql/test/query-tests/Expressions/Regex/UnmatchableDollar.qlref
@@ -1 +1,2 @@
-Expressions/Regex/UnmatchableDollar.ql
+query: Expressions/Regex/UnmatchableDollar.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Expressions/Regex/test.py b/python/ql/test/query-tests/Expressions/Regex/test.py
index 717663e335c..c9aea2d9cef 100644
--- a/python/ql/test/query-tests/Expressions/Regex/test.py
+++ b/python/ql/test/query-tests/Expressions/Regex/test.py
@@ -1,9 +1,9 @@
import re
#Unmatchable caret
-re.compile(b' ^abc')
-re.compile(b"(?s) ^abc")
-re.compile(b"\[^123]")
+re.compile(b' ^abc') # $ Alert[py/regex/unmatchable-caret]
+re.compile(b"(?s) ^abc") # $ Alert[py/regex/unmatchable-caret]
+re.compile(b"\[^123]") # $ Alert[py/regex/unmatchable-caret]
#Likely false positives for unmatchable caret
re.compile(b"[^123]")
@@ -14,21 +14,21 @@ re.compile(b"(?:(?:\n\r?)|^)( *)\S")
re.compile(b"^diff (?:-r [0-9a-f]+ ){1,2}(.*)$")
#Backspace escape
-re.compile(br"[\b\t ]") # Should warn
+re.compile(br"[\b\t ]") # Should warn # $ Alert[py/regex/backspace-escape]
re.compile(br"E\d+\b.*") # Fine
-re.compile(br"E\d+\b[ \b\t]") #Both
+re.compile(br"E\d+\b[ \b\t]") #Both # $ Alert[py/regex/backspace-escape]
#Missing part in named group
-re.compile(br'(P[\w]+)')
-re.compile(br'(_(P[\w]+)|)')
+re.compile(br'(P[\w]+)') # $ Alert[py/regex/incomplete-special-group]
+re.compile(br'(_(P[\w]+)|)') # $ Alert[py/regex/incomplete-special-group]
#This is OK...
re.compile(br'(?P\w+)')
#Unmatchable dollar
-re.compile(b"abc$ ")
-re.compile(b"abc$ (?s)")
-re.compile(b"\[$] ")
+re.compile(b"abc$ ") # $ Alert[py/regex/unmatchable-dollar]
+re.compile(b"abc$ (?s)") # $ Alert[py/regex/unmatchable-dollar]
+re.compile(b"\[$] ") # $ Alert[py/regex/unmatchable-dollar]
#Not unmatchable dollar
re.match(b"[$] ", b"$ ")
@@ -43,9 +43,9 @@ re.match(b"((a$\Z)|b){4}", b"bbba")
re.match(b"(a){00}b", b"b")
#Duplicate character in set
-re.compile(b"[AA]")
-re.compile(b"[000]")
-re.compile(b"[-0-9-]")
+re.compile(b"[AA]") # $ Alert[py/regex/duplicate-in-character-class]
+re.compile(b"[000]") # $ Alert[py/regex/duplicate-in-character-class]
+re.compile(b"[-0-9-]") # $ Alert[py/regex/duplicate-in-character-class]
#Possible false positives
re.compile(b"[S\S]")
@@ -76,8 +76,8 @@ re.compile(br'\w+$(?<=foo)')
#Not OK
-re.compile(br'(?<=foo)^\w+')
-re.compile(br'\w+$(?=foo)')
+re.compile(br'(?<=foo)^\w+') # $ Alert[py/regex/unmatchable-caret]
+re.compile(br'\w+$(?=foo)') # $ Alert[py/regex/unmatchable-dollar]
#OK -- ODASA-ODASA-3968
@@ -134,7 +134,7 @@ VERBOSE_REGEX = r"""
\[ # [
(?P[^]]+) # very permissive!
\] # ]
- """
+ """ # $ Alert[py/regex/duplicate-in-character-class]
# Compiled regular expression marking it as verbose
ODASA_6786 = re.compile(VERBOSE_REGEX, re.VERBOSE)
diff --git a/python/ql/test/query-tests/Expressions/callable/NonCallableCalled.qlref b/python/ql/test/query-tests/Expressions/callable/NonCallableCalled.qlref
index ea8577e6f9f..e26b890fde8 100644
--- a/python/ql/test/query-tests/Expressions/callable/NonCallableCalled.qlref
+++ b/python/ql/test/query-tests/Expressions/callable/NonCallableCalled.qlref
@@ -1 +1,2 @@
-Expressions/NonCallableCalled.ql
\ No newline at end of file
+query: Expressions/NonCallableCalled.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Expressions/callable/test.py b/python/ql/test/query-tests/Expressions/callable/test.py
index 5498fba7292..e37daba131f 100644
--- a/python/ql/test/query-tests/Expressions/callable/test.py
+++ b/python/ql/test/query-tests/Expressions/callable/test.py
@@ -13,9 +13,9 @@ class IsCallable(object):
def call_non_callable(arg):
non = NonCallable()
- non(arg)
- ()()
- []()
+ non(arg) # $ Alert
+ ()() # $ Alert
+ []() # $ Alert
dont_know = MaybeCallable()
dont_know() # Not a violation
ok = IsCallable()
@@ -23,7 +23,7 @@ def call_non_callable(arg):
if hasattr(non, "__call__"):
non(arg) # OK due to guard
if hasattr(non, "__init__"):
- non(arg) # Not OK due to wrong guard
+ non(arg) # Not OK due to wrong guard # $ Alert
import six
@@ -44,7 +44,7 @@ def foo():
raise NotImplemented()
def bar():
- return NotImplemented()
+ return NotImplemented() # $ Alert
# FP due to decorator
@@ -60,7 +60,7 @@ class Foo(object):
@some_decorator
@classmethod
def new_instance(cls, new_arg):
- return cls(new_arg) # TODO: FP
+ return cls(new_arg) # TODO: FP # $ Alert
f1 = Foo(1)
f2 = f1.new_instance(2)
diff --git a/python/ql/test/query-tests/Expressions/comparisons/UselessComparisonTest.qlref b/python/ql/test/query-tests/Expressions/comparisons/UselessComparisonTest.qlref
index fb7f75f9f61..e022932acda 100644
--- a/python/ql/test/query-tests/Expressions/comparisons/UselessComparisonTest.qlref
+++ b/python/ql/test/query-tests/Expressions/comparisons/UselessComparisonTest.qlref
@@ -1 +1,2 @@
-Expressions/Comparisons/UselessComparisonTest.ql
\ No newline at end of file
+query: Expressions/Comparisons/UselessComparisonTest.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Expressions/comparisons/test.py b/python/ql/test/query-tests/Expressions/comparisons/test.py
index aac73f4932e..db0db60e2ed 100644
--- a/python/ql/test/query-tests/Expressions/comparisons/test.py
+++ b/python/ql/test/query-tests/Expressions/comparisons/test.py
@@ -3,16 +3,16 @@
def f(w, x, y, z):
if x < 0 or z < 0:
raise Exception()
- if x >= 0: # Useless test due to x < 0 being false
+ if x >= 0: # Useless test due to x < 0 being false # $ Alert
y += 1
- if z >= 0: # Useless test due to z < 0 being false
+ if z >= 0: # Useless test due to z < 0 being false # $ Alert
y += 1
while w >= 0:
if y < 10:
z += 1
- if y == 15: # Useless test due to y < 10 being true
+ if y == 15: # Useless test due to y < 10 being true # $ Alert
z += 1
- elif y > 7: # Useless test
+ elif y > 7: # Useless test # $ Alert
y -= 1
if y < 10:
y += 1
@@ -24,10 +24,10 @@ def f(w, x, y, z):
def g(w, x, y, z):
if w < x or y < z+2:
raise Exception()
- if w >= x: # Useless test due to w < x being false
+ if w >= x: # Useless test due to w < x being false # $ Alert
pass
if cond:
- if z > y-2: # Useless test due to y < z+2 being false
+ if z > y-2: # Useless test due to y < z+2 being false # $ Alert
y += 1
else:
if z >= y-2: # Not a useless test.
@@ -46,7 +46,7 @@ def validate_series(start, end):
def medium1(x, y):
if x + 1000000000000000 > y + 1000000000000000:
return
- if x > y: # Redundant
+ if x > y: # Redundant # $ Alert
pass
def medium2(x, y):
@@ -70,19 +70,19 @@ def big2(x, y):
def odasa6782_v1(protocol):
if protocol < 0:
protocol = HIGHEST_PROTOCOL
- elif not 0 <= protocol:
+ elif not 0 <= protocol: # $ Alert
raise ValueError()
def odasa6782_v2(protocol):
if protocol < 0:
protocol = HIGHEST_PROTOCOL
- elif not 0 <= protocol <= HIGHEST_PROTOCOL:
+ elif not 0 <= protocol <= HIGHEST_PROTOCOL: # $ Alert
raise ValueError()
def odasa6782_v3(protocol):
if protocol < 0:
protocol = HIGHEST_PROTOCOL
- elif 0 <= protocol <= HIGHEST_PROTOCOL:
+ elif 0 <= protocol <= HIGHEST_PROTOCOL: # $ Alert
pass
else:
raise ValueError()
diff --git a/python/ql/test/query-tests/Expressions/eq/IncorrectComparisonUsingIs.qlref b/python/ql/test/query-tests/Expressions/eq/IncorrectComparisonUsingIs.qlref
index 73123cf7628..df847ee2b1b 100644
--- a/python/ql/test/query-tests/Expressions/eq/IncorrectComparisonUsingIs.qlref
+++ b/python/ql/test/query-tests/Expressions/eq/IncorrectComparisonUsingIs.qlref
@@ -1 +1,2 @@
-Expressions/IncorrectComparisonUsingIs.ql
+query: Expressions/IncorrectComparisonUsingIs.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Expressions/eq/NonPortableComparisonUsingIs.qlref b/python/ql/test/query-tests/Expressions/eq/NonPortableComparisonUsingIs.qlref
index 13c08534293..a62a6a40f60 100644
--- a/python/ql/test/query-tests/Expressions/eq/NonPortableComparisonUsingIs.qlref
+++ b/python/ql/test/query-tests/Expressions/eq/NonPortableComparisonUsingIs.qlref
@@ -1 +1,2 @@
-Expressions/NonPortableComparisonUsingIs.ql
+query: Expressions/NonPortableComparisonUsingIs.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Expressions/eq/expressions_test.py b/python/ql/test/query-tests/Expressions/eq/expressions_test.py
index 3489bf3a1a9..632616583c3 100644
--- a/python/ql/test/query-tests/Expressions/eq/expressions_test.py
+++ b/python/ql/test/query-tests/Expressions/eq/expressions_test.py
@@ -43,12 +43,12 @@ class C:
#Using 'is' when should be using '=='
s = "Hello " + "World"
-if "Hello World" is s:
+if "Hello World" is s: # $ Alert[py/comparison-using-is]
print ("OK")
#This is OK in CPython, but may not be portable
s = str(7)
-if "7" is s:
+if "7" is s: # $ Alert[py/comparison-using-is-non-portable]
print ("OK")
#And some data flow
diff --git a/python/ql/test/query-tests/Expressions/general/CompareConstants.qlref b/python/ql/test/query-tests/Expressions/general/CompareConstants.qlref
index 0e2ab115eee..5b5160d860d 100644
--- a/python/ql/test/query-tests/Expressions/general/CompareConstants.qlref
+++ b/python/ql/test/query-tests/Expressions/general/CompareConstants.qlref
@@ -1 +1,2 @@
-Expressions/CompareConstants.ql
+query: Expressions/CompareConstants.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Expressions/general/CompareIdenticalValues.qlref b/python/ql/test/query-tests/Expressions/general/CompareIdenticalValues.qlref
index 4bc0ec69fc0..ad4cbb7600e 100644
--- a/python/ql/test/query-tests/Expressions/general/CompareIdenticalValues.qlref
+++ b/python/ql/test/query-tests/Expressions/general/CompareIdenticalValues.qlref
@@ -1 +1,2 @@
-Expressions/CompareIdenticalValues.ql
+query: Expressions/CompareIdenticalValues.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Expressions/general/CompareIdenticalValuesMissingSelf.qlref b/python/ql/test/query-tests/Expressions/general/CompareIdenticalValuesMissingSelf.qlref
index f19a0dee436..48f4d302afb 100644
--- a/python/ql/test/query-tests/Expressions/general/CompareIdenticalValuesMissingSelf.qlref
+++ b/python/ql/test/query-tests/Expressions/general/CompareIdenticalValuesMissingSelf.qlref
@@ -1 +1,2 @@
-Expressions/CompareIdenticalValuesMissingSelf.ql
\ No newline at end of file
+query: Expressions/CompareIdenticalValuesMissingSelf.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Expressions/general/ContainsNonContainer.qlref b/python/ql/test/query-tests/Expressions/general/ContainsNonContainer.qlref
index 71df405e72c..b52c39ed26d 100644
--- a/python/ql/test/query-tests/Expressions/general/ContainsNonContainer.qlref
+++ b/python/ql/test/query-tests/Expressions/general/ContainsNonContainer.qlref
@@ -1 +1,2 @@
-Expressions/ContainsNonContainer.ql
+query: Expressions/ContainsNonContainer.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Expressions/general/DuplicateKeyInDictionaryLiteral.qlref b/python/ql/test/query-tests/Expressions/general/DuplicateKeyInDictionaryLiteral.qlref
index a1bb7109882..23123f18749 100644
--- a/python/ql/test/query-tests/Expressions/general/DuplicateKeyInDictionaryLiteral.qlref
+++ b/python/ql/test/query-tests/Expressions/general/DuplicateKeyInDictionaryLiteral.qlref
@@ -1 +1,2 @@
-Expressions/DuplicateKeyInDictionaryLiteral.ql
\ No newline at end of file
+query: Expressions/DuplicateKeyInDictionaryLiteral.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Expressions/general/EqualsNone.qlref b/python/ql/test/query-tests/Expressions/general/EqualsNone.qlref
index 8d9699258e2..026a3f5bbc2 100644
--- a/python/ql/test/query-tests/Expressions/general/EqualsNone.qlref
+++ b/python/ql/test/query-tests/Expressions/general/EqualsNone.qlref
@@ -1 +1,2 @@
-Expressions/EqualsNone.ql
\ No newline at end of file
+query: Expressions/EqualsNone.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Expressions/general/ExpectedMappingForFormatString.qlref b/python/ql/test/query-tests/Expressions/general/ExpectedMappingForFormatString.qlref
index 83e92584ef2..fd322b848dc 100644
--- a/python/ql/test/query-tests/Expressions/general/ExpectedMappingForFormatString.qlref
+++ b/python/ql/test/query-tests/Expressions/general/ExpectedMappingForFormatString.qlref
@@ -1 +1,2 @@
-Expressions/ExpectedMappingForFormatString.ql
\ No newline at end of file
+query: Expressions/ExpectedMappingForFormatString.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Expressions/general/ExplicitCallToDel.qlref b/python/ql/test/query-tests/Expressions/general/ExplicitCallToDel.qlref
index 932f1a3d366..451bd74eee0 100644
--- a/python/ql/test/query-tests/Expressions/general/ExplicitCallToDel.qlref
+++ b/python/ql/test/query-tests/Expressions/general/ExplicitCallToDel.qlref
@@ -1 +1,2 @@
-Expressions/ExplicitCallToDel.ql
\ No newline at end of file
+query: Expressions/ExplicitCallToDel.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Expressions/general/HashedButNoHash.qlref b/python/ql/test/query-tests/Expressions/general/HashedButNoHash.qlref
index ee53e367499..f30fd92870f 100644
--- a/python/ql/test/query-tests/Expressions/general/HashedButNoHash.qlref
+++ b/python/ql/test/query-tests/Expressions/general/HashedButNoHash.qlref
@@ -1 +1,2 @@
-Expressions/HashedButNoHash.ql
\ No newline at end of file
+query: Expressions/HashedButNoHash.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Expressions/general/UnnecessaryLambda.qlref b/python/ql/test/query-tests/Expressions/general/UnnecessaryLambda.qlref
index 49b3873f83c..9141c5e49a6 100644
--- a/python/ql/test/query-tests/Expressions/general/UnnecessaryLambda.qlref
+++ b/python/ql/test/query-tests/Expressions/general/UnnecessaryLambda.qlref
@@ -1 +1,2 @@
-Expressions/UnnecessaryLambda.ql
\ No newline at end of file
+query: Expressions/UnnecessaryLambda.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Expressions/general/UnsupportedFormatCharacter.qlref b/python/ql/test/query-tests/Expressions/general/UnsupportedFormatCharacter.qlref
index 3cb459229e4..8e50b947401 100644
--- a/python/ql/test/query-tests/Expressions/general/UnsupportedFormatCharacter.qlref
+++ b/python/ql/test/query-tests/Expressions/general/UnsupportedFormatCharacter.qlref
@@ -1 +1,2 @@
-Expressions/UnsupportedFormatCharacter.ql
\ No newline at end of file
+query: Expressions/UnsupportedFormatCharacter.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Expressions/general/WrongNumberArgumentsForFormat.qlref b/python/ql/test/query-tests/Expressions/general/WrongNumberArgumentsForFormat.qlref
index 0d127e1b618..744334a6aeb 100644
--- a/python/ql/test/query-tests/Expressions/general/WrongNumberArgumentsForFormat.qlref
+++ b/python/ql/test/query-tests/Expressions/general/WrongNumberArgumentsForFormat.qlref
@@ -1 +1,2 @@
-Expressions/WrongNumberArgumentsForFormat.ql
\ No newline at end of file
+query: Expressions/WrongNumberArgumentsForFormat.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Expressions/general/compare.py b/python/ql/test/query-tests/Expressions/general/compare.py
index 141b5e6a028..c48e06f4b1c 100644
--- a/python/ql/test/query-tests/Expressions/general/compare.py
+++ b/python/ql/test/query-tests/Expressions/general/compare.py
@@ -5,12 +5,12 @@ a == b
a.x == b.x
#Same variables
-a == a
-a.x == a.x
+a == a # $ Alert[py/comparison-of-identical-expressions]
+a.x == a.x # $ Alert[py/comparison-of-identical-expressions]
#Compare constants
-1 == 1
-1 == 2
+1 == 1 # $ Alert[py/comparison-of-constants]
+1 == 2 # $ Alert[py/comparison-of-constants]
#Maybe missing self
class X(object):
@@ -19,7 +19,7 @@ class X(object):
self.x = x
def missing_self(self, x):
- if x == x:
+ if x == x: # $ Alert[py/comparison-missing-self]
print ("Yes")
#Compare constants in assert -- ok
diff --git a/python/ql/test/query-tests/Expressions/general/expressions_test.py b/python/ql/test/query-tests/Expressions/general/expressions_test.py
index 5e07b58e204..71e0d1ba7cf 100644
--- a/python/ql/test/query-tests/Expressions/general/expressions_test.py
+++ b/python/ql/test/query-tests/Expressions/general/expressions_test.py
@@ -1,16 +1,16 @@
#encoding: utf-8
def dup_key():
- return { 1: -1,
+ return { 1: -1, # $ Alert[py/duplicate-key-dict-literal]
1: -2,
- u'a' : u'A',
+ u'a' : u'A', # $ Alert[py/duplicate-key-dict-literal]
u'a' : u'B'
}
def simple_func(*args, **kwrgs): pass
#Unnecessary lambdas
-lambda arg0, arg1: simple_func(arg0, arg1)
-lambda arg0, *arg1: simple_func(arg0, *arg1)
-lambda arg0, **arg1: simple_func(arg0, **arg1)
+lambda arg0, arg1: simple_func(arg0, arg1) # $ Alert[py/unnecessary-lambda]
+lambda arg0, *arg1: simple_func(arg0, *arg1) # $ Alert[py/unnecessary-lambda]
+lambda arg0, **arg1: simple_func(arg0, **arg1) # $ Alert[py/unnecessary-lambda]
# these lambdas are_ necessary
lambda arg0, arg1=1: simple_func(arg0, arg1)
lambda arg0, arg1: simple_func(arg0, *arg1)
@@ -34,12 +34,12 @@ def call_non_callable(arg):
dont_know() # Not a violation
#Explicit call to __del__
-x.__del__()
+x.__del__() # $ Alert[py/explicit-call-to-delete]
#Unhashable object
def func():
mapping = dict(); unhash = list()
- return mapping[unhash]
+ return mapping[unhash] # $ Alert[py/hash-unhashable-value]
#Using 'is' when should be using '=='
s = "Hello " + "World"
@@ -86,9 +86,9 @@ class XIter(object):
def non_container():
seq = XIter()
- if 1 in seq:
+ if 1 in seq: # $ Alert[py/member-test-non-container]
pass
- if 1 not in seq:
+ if 1 not in seq: # $ Alert[py/member-test-non-container]
pass
#Container inheriting from builtin
@@ -112,7 +112,7 @@ def is_container():
#Equals none
def x(arg):
- return arg == None
+ return arg == None # $ Alert[py/test-equals-none]
class NotMyDict(object):
@@ -130,7 +130,7 @@ class SubTest(Test):
# This is permitted and required.
Test.__del__(self)
# This is a violation.
- self.__del__()
+ self.__del__() # $ Alert[py/explicit-call-to-delete]
# This is an alternate syntax for the super() call, and hence OK.
super(SubTest, self).__del__()
# This is the Python 3 spelling of the same.
@@ -138,15 +138,15 @@ class SubTest(Test):
#Some more lambdas
#Unnecessary lambdas
-lambda arg0: len(arg0)
-lambda arg0: XIter.next(arg0)
+lambda arg0: len(arg0) # $ Alert[py/unnecessary-lambda]
+lambda arg0: XIter.next(arg0) # $ Alert[py/unnecessary-lambda]
class UL(object):
def f(self, x):
pass
def g(self):
- return lambda x: self.f(x)
+ return lambda x: self.f(x) # $ Alert[py/unnecessary-lambda]
# these lambdas are necessary
lambda arg0: XIter.next(arg0, arg1)
diff --git a/python/ql/test/query-tests/Expressions/general/str_fmt_test.py b/python/ql/test/query-tests/Expressions/general/str_fmt_test.py
index e941b842c31..f7441ef9a8a 100644
--- a/python/ql/test/query-tests/Expressions/general/str_fmt_test.py
+++ b/python/ql/test/query-tests/Expressions/general/str_fmt_test.py
@@ -2,16 +2,16 @@
def expected_mapping_for_fmt_string():
x = [ u'list', u'not', u'mapping' ]
- print (u"%(name)s" % x)
+ print (u"%(name)s" % x) # $ Alert[py/percent-format/not-mapping]
def unsupported_format_char(arg):
- print (u"%Z" % arg)
+ print (u"%Z" % arg) # $ Alert[py/percent-format/unsupported-character]
def wrong_arg_count_format(arg):
- print(u"%s %s" % (arg, arg, 0))
+ print(u"%s %s" % (arg, arg, 0)) # $ Alert[py/percent-format/wrong-arguments]
format = u"%hd"
args = (1, u'foo')
- print(format % args)
+ print(format % args) # $ Alert[py/percent-format/wrong-arguments]
def ok():
diff --git a/python/ql/test/query-tests/Expressions/strings/UnintentionalImplicitStringConcatenation.qlref b/python/ql/test/query-tests/Expressions/strings/UnintentionalImplicitStringConcatenation.qlref
index c305fd129f8..7159e5c7972 100644
--- a/python/ql/test/query-tests/Expressions/strings/UnintentionalImplicitStringConcatenation.qlref
+++ b/python/ql/test/query-tests/Expressions/strings/UnintentionalImplicitStringConcatenation.qlref
@@ -1 +1,2 @@
-Expressions/UnintentionalImplicitStringConcatenation.ql
\ No newline at end of file
+query: Expressions/UnintentionalImplicitStringConcatenation.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Expressions/strings/test.py b/python/ql/test/query-tests/Expressions/strings/test.py
index 15b3c9216e3..1767a2d109b 100644
--- a/python/ql/test/query-tests/Expressions/strings/test.py
+++ b/python/ql/test/query-tests/Expressions/strings/test.py
@@ -15,13 +15,13 @@ def test():
error1 = [
"foo",
"/usr/local"
- "/usr/bin"
+ "/usr/bin" # $ Alert
]
error2 = [
"foo" +
"bar",
"/usr/local"
- "/usr/bin"
+ "/usr/bin" # $ Alert
]
#Examples from documentation
@@ -31,9 +31,9 @@ def unclear():
return [
"first part of long string"
- " and the second part",
+ " and the second part", # $ Alert
"/usr/local"
- "/usr/bin"
+ "/usr/bin" # $ Alert
]
def clarified():
diff --git a/python/ql/test/query-tests/Expressions/super/CallToSuperWrongClass.qlref b/python/ql/test/query-tests/Expressions/super/CallToSuperWrongClass.qlref
index c3beeaede04..e1ed0c122be 100644
--- a/python/ql/test/query-tests/Expressions/super/CallToSuperWrongClass.qlref
+++ b/python/ql/test/query-tests/Expressions/super/CallToSuperWrongClass.qlref
@@ -1 +1,2 @@
-Expressions/CallToSuperWrongClass.ql
\ No newline at end of file
+query: Expressions/CallToSuperWrongClass.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Expressions/super/test.py b/python/ql/test/query-tests/Expressions/super/test.py
index e2e667cd25d..947bc3814b2 100644
--- a/python/ql/test/query-tests/Expressions/super/test.py
+++ b/python/ql/test/query-tests/Expressions/super/test.py
@@ -7,7 +7,7 @@ class MyDict(dict):
class NotMyDict(object):
def f(self):
- super(MyDict, self).f()
+ super(MyDict, self).f() # $ Alert
#Splitting
PY2 = sys.version_info[0] == 2
diff --git a/python/ql/test/query-tests/Functions/ModificationOfParameterWithDefault/ModificationOfParameterWithDefault.qlref b/python/ql/test/query-tests/Functions/ModificationOfParameterWithDefault/ModificationOfParameterWithDefault.qlref
index 8c4044e8fee..e8937358e32 100644
--- a/python/ql/test/query-tests/Functions/ModificationOfParameterWithDefault/ModificationOfParameterWithDefault.qlref
+++ b/python/ql/test/query-tests/Functions/ModificationOfParameterWithDefault/ModificationOfParameterWithDefault.qlref
@@ -1 +1 @@
-Functions/ModificationOfParameterWithDefault.ql
+query: Functions/ModificationOfParameterWithDefault.ql
diff --git a/python/ql/test/query-tests/Functions/general/DeprecatedSliceMethod.qlref b/python/ql/test/query-tests/Functions/general/DeprecatedSliceMethod.qlref
index c38b8d1f761..3043411c1ce 100644
--- a/python/ql/test/query-tests/Functions/general/DeprecatedSliceMethod.qlref
+++ b/python/ql/test/query-tests/Functions/general/DeprecatedSliceMethod.qlref
@@ -1 +1,2 @@
-Functions/DeprecatedSliceMethod.ql
\ No newline at end of file
+query: Functions/DeprecatedSliceMethod.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Functions/general/ExplicitReturnInInit.qlref b/python/ql/test/query-tests/Functions/general/ExplicitReturnInInit.qlref
index a23550c4865..df13334dcbf 100644
--- a/python/ql/test/query-tests/Functions/general/ExplicitReturnInInit.qlref
+++ b/python/ql/test/query-tests/Functions/general/ExplicitReturnInInit.qlref
@@ -1 +1,2 @@
-Functions/ExplicitReturnInInit.ql
\ No newline at end of file
+query: Functions/ExplicitReturnInInit.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Functions/general/InitIsGenerator.qlref b/python/ql/test/query-tests/Functions/general/InitIsGenerator.qlref
index a3df140ff1e..2662a7ca03a 100644
--- a/python/ql/test/query-tests/Functions/general/InitIsGenerator.qlref
+++ b/python/ql/test/query-tests/Functions/general/InitIsGenerator.qlref
@@ -1 +1,2 @@
-Functions/InitIsGenerator.ql
\ No newline at end of file
+query: Functions/InitIsGenerator.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Functions/general/IterReturnsNonIterator.qlref b/python/ql/test/query-tests/Functions/general/IterReturnsNonIterator.qlref
index 3d0965f7b11..14655b261d4 100644
--- a/python/ql/test/query-tests/Functions/general/IterReturnsNonIterator.qlref
+++ b/python/ql/test/query-tests/Functions/general/IterReturnsNonIterator.qlref
@@ -1 +1 @@
-Functions/IterReturnsNonIterator.ql
+query: Functions/IterReturnsNonIterator.ql
diff --git a/python/ql/test/query-tests/Functions/general/OverlyComplexDelMethod.qlref b/python/ql/test/query-tests/Functions/general/OverlyComplexDelMethod.qlref
index 601501aac30..90dba842c0e 100644
--- a/python/ql/test/query-tests/Functions/general/OverlyComplexDelMethod.qlref
+++ b/python/ql/test/query-tests/Functions/general/OverlyComplexDelMethod.qlref
@@ -1 +1,2 @@
-Functions/OverlyComplexDelMethod.ql
+query: Functions/OverlyComplexDelMethod.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Functions/general/SignatureOverriddenMethod.qlref b/python/ql/test/query-tests/Functions/general/SignatureOverriddenMethod.qlref
index a306477b3b4..5470a05e0e4 100644
--- a/python/ql/test/query-tests/Functions/general/SignatureOverriddenMethod.qlref
+++ b/python/ql/test/query-tests/Functions/general/SignatureOverriddenMethod.qlref
@@ -1 +1,2 @@
-Functions/SignatureOverriddenMethod.ql
+query: Functions/SignatureOverriddenMethod.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Functions/general/SignatureSpecialMethods.qlref b/python/ql/test/query-tests/Functions/general/SignatureSpecialMethods.qlref
index bc1b29b6c0d..ab188ef5bc2 100644
--- a/python/ql/test/query-tests/Functions/general/SignatureSpecialMethods.qlref
+++ b/python/ql/test/query-tests/Functions/general/SignatureSpecialMethods.qlref
@@ -1 +1,2 @@
-Functions/SignatureSpecialMethods.ql
\ No newline at end of file
+query: Functions/SignatureSpecialMethods.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Functions/general/explicit_return_in_init.py b/python/ql/test/query-tests/Functions/general/explicit_return_in_init.py
index 47a2933ad6e..9024b13aa78 100644
--- a/python/ql/test/query-tests/Functions/general/explicit_return_in_init.py
+++ b/python/ql/test/query-tests/Functions/general/explicit_return_in_init.py
@@ -1,7 +1,7 @@
class ExplicitReturnInInit(object):
def __init__(self):
- return self
+ return self # $ Alert[py/explicit-return-in-init]
# These are OK
class ExplicitReturnNoneInInit(object):
@@ -29,7 +29,7 @@ class InitCallsInit(InitCallsError):
class InitIsGenerator(object):
- def __init__(self):
+ def __init__(self): # $ Alert[py/init-method-is-generator]
yield self
# OK as it returns result of a call to super().__init__()
@@ -99,4 +99,4 @@ class InitReturnsCallResult6(object):
p = procedure_implicit_none()
else:
p = not_ok
- return p()
+ return p() # $ Alert[py/explicit-return-in-init]
diff --git a/python/ql/test/query-tests/Functions/general/functions_test.py b/python/ql/test/query-tests/Functions/general/functions_test.py
index 741599abd5b..a306ef8ccc8 100644
--- a/python/ql/test/query-tests/Functions/general/functions_test.py
+++ b/python/ql/test/query-tests/Functions/general/functions_test.py
@@ -92,13 +92,13 @@ def ok_to_ignore():
class DeprecatedSliceMethods(object):
- def __getslice__(self, start, stop):
+ def __getslice__(self, start, stop): # $ Alert[py/deprecated-slice-method]
pass
- def __setslice__(self, start, stop, value):
+ def __setslice__(self, start, stop, value): # $ Alert[py/deprecated-slice-method]
pass
- def __delslice__(self, start, stop):
+ def __delslice__(self, start, stop): # $ Alert[py/deprecated-slice-method]
pass
diff --git a/python/ql/test/query-tests/Functions/general/om_test.py b/python/ql/test/query-tests/Functions/general/om_test.py
index 959ed6bfe34..edaa81bd062 100644
--- a/python/ql/test/query-tests/Functions/general/om_test.py
+++ b/python/ql/test/query-tests/Functions/general/om_test.py
@@ -29,10 +29,10 @@ class Derived(Base):
def ok2(self, arg1, arg2 = 2, arg3 = 3):
return arg1, arg2, arg3
- def grossly_wrong1(self, arg1):
+ def grossly_wrong1(self, arg1): # $ Alert[py/inheritance/signature-mismatch]
return arg1
- def grossly_wrong2(self, arg1, arg2, arg3):
+ def grossly_wrong2(self, arg1, arg2, arg3): # $ Alert[py/inheritance/signature-mismatch]
return arg1, arg2, arg3
def strictly_wrong1(self, arg1):
@@ -56,19 +56,19 @@ class Special(object):
class WrongSpecials(object):
- def __div__(self, x, y):
+ def __div__(self, x, y): # $ Alert[py/special-method-wrong-signature]
return self, x, y
- def __mul__(self):
+ def __mul__(self): # $ Alert[py/special-method-wrong-signature]
return self
- def __neg__(self, other):
+ def __neg__(self, other): # $ Alert[py/special-method-wrong-signature]
return self, other
- def __exit__(self, arg0, arg1):
+ def __exit__(self, arg0, arg1): # $ Alert[py/special-method-wrong-signature]
return arg0 == arg1
- def __repr__():
+ def __repr__(): # $ Alert[py/special-method-wrong-signature]
return ""
def __add__(self, other="Unused default"):
@@ -80,7 +80,7 @@ class WrongSpecials(object):
class OKSpecials(object):
- def __del__():
+ def __del__(): # $ Alert[py/special-method-wrong-signature]
state = some_state()
def __del__(self):
diff --git a/python/ql/test/query-tests/Functions/general/protocols.py b/python/ql/test/query-tests/Functions/general/protocols.py
index dd12fc3ed40..68f0aaf29c0 100644
--- a/python/ql/test/query-tests/Functions/general/protocols.py
+++ b/python/ql/test/query-tests/Functions/general/protocols.py
@@ -71,7 +71,7 @@ class AlmostIterable(object):
class MegaDel(object):
- def __del__(self):
+ def __del__(self): # $ Alert[py/overly-complex-delete]
a = self.x + self.y
if a:
print(a)
diff --git a/python/ql/test/query-tests/Functions/iterators/IterReturnsNonSelf.qlref b/python/ql/test/query-tests/Functions/iterators/IterReturnsNonSelf.qlref
index b806215d26c..828fca864da 100644
--- a/python/ql/test/query-tests/Functions/iterators/IterReturnsNonSelf.qlref
+++ b/python/ql/test/query-tests/Functions/iterators/IterReturnsNonSelf.qlref
@@ -1 +1,2 @@
-Functions/IterReturnsNonSelf.ql
\ No newline at end of file
+query: Functions/IterReturnsNonSelf.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Functions/iterators/test.py b/python/ql/test/query-tests/Functions/iterators/test.py
index ced389967e4..6244f5dc10b 100644
--- a/python/ql/test/query-tests/Functions/iterators/test.py
+++ b/python/ql/test/query-tests/Functions/iterators/test.py
@@ -2,7 +2,7 @@ class Bad1:
def __next__(self):
return 0
- def __iter__(self): # BAD: Iter does not return self
+ def __iter__(self): # BAD: Iter does not return self # $ Alert
yield 0
class Good1:
@@ -48,6 +48,6 @@ class FalsePositive1:
self._it = iter(self)
return next(self._it)
- def __iter__(self): # SPURIOUS, GOOD: implementation of next ensures the iterator is equivalent to the one returned by iter, but this is not detected.
+ def __iter__(self): # SPURIOUS, GOOD: implementation of next ensures the iterator is equivalent to the one returned by iter, but this is not detected. # $ Alert
yield 0
yield 0
\ No newline at end of file
diff --git a/python/ql/test/query-tests/Functions/overriding/IncorrectlyOverriddenMethod.qlref b/python/ql/test/query-tests/Functions/overriding/IncorrectlyOverriddenMethod.qlref
index d1637c1f1d3..cc2a5f9f73d 100644
--- a/python/ql/test/query-tests/Functions/overriding/IncorrectlyOverriddenMethod.qlref
+++ b/python/ql/test/query-tests/Functions/overriding/IncorrectlyOverriddenMethod.qlref
@@ -1 +1 @@
-Functions/IncorrectlyOverriddenMethod.ql
\ No newline at end of file
+query: Functions/IncorrectlyOverriddenMethod.ql
diff --git a/python/ql/test/query-tests/Functions/overriding/IncorrectlySpecifiedOverriddenMethod.qlref b/python/ql/test/query-tests/Functions/overriding/IncorrectlySpecifiedOverriddenMethod.qlref
index 8a07cb1297e..958fcc629ff 100644
--- a/python/ql/test/query-tests/Functions/overriding/IncorrectlySpecifiedOverriddenMethod.qlref
+++ b/python/ql/test/query-tests/Functions/overriding/IncorrectlySpecifiedOverriddenMethod.qlref
@@ -1 +1 @@
-Functions/IncorrectlySpecifiedOverriddenMethod.ql
\ No newline at end of file
+query: Functions/IncorrectlySpecifiedOverriddenMethod.ql
diff --git a/python/ql/test/query-tests/Functions/overriding/WrongNameForArgumentInCall.qlref b/python/ql/test/query-tests/Functions/overriding/WrongNameForArgumentInCall.qlref
index 3599f204f55..e68f904bc81 100644
--- a/python/ql/test/query-tests/Functions/overriding/WrongNameForArgumentInCall.qlref
+++ b/python/ql/test/query-tests/Functions/overriding/WrongNameForArgumentInCall.qlref
@@ -1 +1 @@
-Expressions/WrongNameForArgumentInCall.ql
\ No newline at end of file
+query: Expressions/WrongNameForArgumentInCall.ql
diff --git a/python/ql/test/query-tests/Functions/overriding/WrongNumberArgumentsInCall.qlref b/python/ql/test/query-tests/Functions/overriding/WrongNumberArgumentsInCall.qlref
index 1bffe8f1cad..ee0b95d7b07 100644
--- a/python/ql/test/query-tests/Functions/overriding/WrongNumberArgumentsInCall.qlref
+++ b/python/ql/test/query-tests/Functions/overriding/WrongNumberArgumentsInCall.qlref
@@ -1 +1 @@
-Expressions/WrongNumberArgumentsInCall.ql
\ No newline at end of file
+query: Expressions/WrongNumberArgumentsInCall.ql
diff --git a/python/ql/test/query-tests/Functions/return_values/ConsistentReturns.qlref b/python/ql/test/query-tests/Functions/return_values/ConsistentReturns.qlref
index 0904074f25b..6f10808f42b 100644
--- a/python/ql/test/query-tests/Functions/return_values/ConsistentReturns.qlref
+++ b/python/ql/test/query-tests/Functions/return_values/ConsistentReturns.qlref
@@ -1 +1,2 @@
-Functions/ConsistentReturns.ql
+query: Functions/ConsistentReturns.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Functions/return_values/ReturnConsistentTupleSizes.qlref b/python/ql/test/query-tests/Functions/return_values/ReturnConsistentTupleSizes.qlref
index c91661b33cf..c7eaa3205b2 100644
--- a/python/ql/test/query-tests/Functions/return_values/ReturnConsistentTupleSizes.qlref
+++ b/python/ql/test/query-tests/Functions/return_values/ReturnConsistentTupleSizes.qlref
@@ -1 +1,2 @@
-Functions/ReturnConsistentTupleSizes.ql
+query: Functions/ReturnConsistentTupleSizes.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Functions/return_values/ReturnValueIgnored.qlref b/python/ql/test/query-tests/Functions/return_values/ReturnValueIgnored.qlref
index 61002533ef4..ded6bf8e609 100644
--- a/python/ql/test/query-tests/Functions/return_values/ReturnValueIgnored.qlref
+++ b/python/ql/test/query-tests/Functions/return_values/ReturnValueIgnored.qlref
@@ -1 +1,2 @@
-Functions/ReturnValueIgnored.ql
\ No newline at end of file
+query: Functions/ReturnValueIgnored.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Functions/return_values/UseImplicitNoneReturnValue.qlref b/python/ql/test/query-tests/Functions/return_values/UseImplicitNoneReturnValue.qlref
index b23115e8950..af71ab6388e 100644
--- a/python/ql/test/query-tests/Functions/return_values/UseImplicitNoneReturnValue.qlref
+++ b/python/ql/test/query-tests/Functions/return_values/UseImplicitNoneReturnValue.qlref
@@ -1 +1,2 @@
-Functions/UseImplicitNoneReturnValue.ql
\ No newline at end of file
+query: Functions/UseImplicitNoneReturnValue.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Functions/return_values/functions_test.py b/python/ql/test/query-tests/Functions/return_values/functions_test.py
index 9f72a7fec60..ac87960e82e 100644
--- a/python/ql/test/query-tests/Functions/return_values/functions_test.py
+++ b/python/ql/test/query-tests/Functions/return_values/functions_test.py
@@ -15,11 +15,11 @@ def ok2(x):
else:
return "Hi"
-def cr1(x):
+def cr1(x): # $ Alert[py/mixed-returns]
if x:
return 4
-def cr2(x):
+def cr2(x): # $ Alert[py/mixed-returns]
if x:
return 4
else:
@@ -74,7 +74,7 @@ def ok4(x):
def use_implicit_return_value(arg):
- x = do_nothing()
+ x = do_nothing() # $ Alert[py/procedure-return-value-used]
return call_non_callable(arg)
#The return in the lambda is OK as it is auto-generated
@@ -156,9 +156,9 @@ def do_nothing():
def return_value_ignored():
- ok2()
- ok4()
- sorted([1,2])
+ ok2() # $ Alert[py/ignored-return-value]
+ ok4() # $ Alert[py/ignored-return-value]
+ sorted([1,2]) # $ Alert[py/ignored-return-value]
d = {}
@@ -231,7 +231,7 @@ def mutli_return(arg):
if arg:
return do_something()
else:
- return do_nothing()
+ return do_nothing() # $ Alert[py/procedure-return-value-used]
#Modification of parameter with default
@@ -303,7 +303,7 @@ y = foo()
# Returning tuples with different sizes
-def returning_different_tuple_sizes(x):
+def returning_different_tuple_sizes(x): # $ Alert[py/mixed-tuple-returns]
if x:
return 1,2
else:
@@ -333,7 +333,7 @@ def mismatched_multi_assign(x):
return a,b
-def ok_match(x): # FP
+def ok_match(x): # FP # $ Alert[py/mixed-returns]
match x:
case True | 'true':
return 0
@@ -341,7 +341,7 @@ def ok_match(x): # FP
raise ValueError(x)
-def ok_match2(x): # FP
+def ok_match2(x): # FP # $ Alert[py/mixed-returns]
match x:
case None:
return 0
diff --git a/python/ql/test/query-tests/Imports/PyCheckerTests/ImportandImportFrom.qlref b/python/ql/test/query-tests/Imports/PyCheckerTests/ImportandImportFrom.qlref
index 3d50843db7e..ed5a37e9d47 100644
--- a/python/ql/test/query-tests/Imports/PyCheckerTests/ImportandImportFrom.qlref
+++ b/python/ql/test/query-tests/Imports/PyCheckerTests/ImportandImportFrom.qlref
@@ -1 +1,2 @@
-Imports/ImportandImportFrom.ql
+query: Imports/ImportandImportFrom.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Imports/PyCheckerTests/ModuleImportsItself.qlref b/python/ql/test/query-tests/Imports/PyCheckerTests/ModuleImportsItself.qlref
index e6bc27b3065..a5a25747abf 100644
--- a/python/ql/test/query-tests/Imports/PyCheckerTests/ModuleImportsItself.qlref
+++ b/python/ql/test/query-tests/Imports/PyCheckerTests/ModuleImportsItself.qlref
@@ -1 +1,2 @@
-Imports/ModuleImportsItself.ql
+query: Imports/ModuleImportsItself.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Imports/PyCheckerTests/imports_test.py b/python/ql/test/query-tests/Imports/PyCheckerTests/imports_test.py
index 6224c788c5e..b8fa4a7ae37 100644
--- a/python/ql/test/query-tests/Imports/PyCheckerTests/imports_test.py
+++ b/python/ql/test/query-tests/Imports/PyCheckerTests/imports_test.py
@@ -1,11 +1,11 @@
#Import and import from
-import test_module2
+import test_module2 # $ Alert[py/import-and-import-from]
from test_module2 import func
#Module imports itself
-import imports_test
+import imports_test # $ Alert[py/import-own-module]
import pkg_ok
import pkg_notok
diff --git a/python/ql/test/query-tests/Imports/PyCheckerTests/pkg_notok/__init__.py b/python/ql/test/query-tests/Imports/PyCheckerTests/pkg_notok/__init__.py
index b0e269d67a5..ecfa5291dc3 100644
--- a/python/ql/test/query-tests/Imports/PyCheckerTests/pkg_notok/__init__.py
+++ b/python/ql/test/query-tests/Imports/PyCheckerTests/pkg_notok/__init__.py
@@ -1,7 +1,7 @@
class Foo(object):
pass
-import pkg_notok
+import pkg_notok # $ Alert[py/import-and-import-from] Alert[py/import-own-module]
# This import is a bit tricky. It will make `bar` available in as `pkg_notok.bar` as a
# side effect (see https://docs.python.org/3/reference/import.html#submodules), but the
@@ -9,6 +9,6 @@ import pkg_notok
# module imports itself.
import pkg_notok.bar
-from pkg_notok import Foo
-from pkg_notok import Foo as NotOkFoo
-from pkg_notok import *
+from pkg_notok import Foo # $ Alert[py/import-own-module]
+from pkg_notok import Foo as NotOkFoo # $ Alert[py/import-own-module]
+from pkg_notok import * # $ Alert[py/import-own-module]
diff --git a/python/ql/test/query-tests/Imports/cyclic-module-annotations-fp/ModuleLevelCyclicImport.qlref b/python/ql/test/query-tests/Imports/cyclic-module-annotations-fp/ModuleLevelCyclicImport.qlref
index 8b9bc8c123a..e0e35483fed 100644
--- a/python/ql/test/query-tests/Imports/cyclic-module-annotations-fp/ModuleLevelCyclicImport.qlref
+++ b/python/ql/test/query-tests/Imports/cyclic-module-annotations-fp/ModuleLevelCyclicImport.qlref
@@ -1 +1,2 @@
-Imports/ModuleLevelCyclicImport.ql
+query: Imports/ModuleLevelCyclicImport.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Imports/cyclic-module-annotations-fp/module3.py b/python/ql/test/query-tests/Imports/cyclic-module-annotations-fp/module3.py
index 83f5eda9557..e3d76ff53a7 100644
--- a/python/ql/test/query-tests/Imports/cyclic-module-annotations-fp/module3.py
+++ b/python/ql/test/query-tests/Imports/cyclic-module-annotations-fp/module3.py
@@ -5,4 +5,4 @@ import module4
@dataclasses.dataclass()
class Foo:
- bars: typing.List[module4.Bar]
+ bars: typing.List[module4.Bar] # $ Alert
diff --git a/python/ql/test/query-tests/Imports/cyclic-module-annotations-fp/module4.py b/python/ql/test/query-tests/Imports/cyclic-module-annotations-fp/module4.py
index b6da208fbe3..e7864e9b6ca 100644
--- a/python/ql/test/query-tests/Imports/cyclic-module-annotations-fp/module4.py
+++ b/python/ql/test/query-tests/Imports/cyclic-module-annotations-fp/module4.py
@@ -5,5 +5,5 @@ import module3
@dataclasses.dataclass()
class Bar:
- def is_in_foo(self, foo: module3.Foo):
+ def is_in_foo(self, foo: module3.Foo): # $ Alert
return self in foo.bars
diff --git a/python/ql/test/query-tests/Imports/cyclic-module-package-fp/false-negative/CyclicImport.qlref b/python/ql/test/query-tests/Imports/cyclic-module-package-fp/false-negative/CyclicImport.qlref
index 814bba9fad6..082797c9226 100644
--- a/python/ql/test/query-tests/Imports/cyclic-module-package-fp/false-negative/CyclicImport.qlref
+++ b/python/ql/test/query-tests/Imports/cyclic-module-package-fp/false-negative/CyclicImport.qlref
@@ -1 +1,2 @@
-Imports/CyclicImport.ql
\ No newline at end of file
+query: Imports/CyclicImport.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Imports/cyclic-module-package-fp/false-negative/ModuleLevelCyclicImport.qlref b/python/ql/test/query-tests/Imports/cyclic-module-package-fp/false-negative/ModuleLevelCyclicImport.qlref
index 5119f8fdaae..e0e35483fed 100644
--- a/python/ql/test/query-tests/Imports/cyclic-module-package-fp/false-negative/ModuleLevelCyclicImport.qlref
+++ b/python/ql/test/query-tests/Imports/cyclic-module-package-fp/false-negative/ModuleLevelCyclicImport.qlref
@@ -1 +1,2 @@
-Imports/ModuleLevelCyclicImport.ql
\ No newline at end of file
+query: Imports/ModuleLevelCyclicImport.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Imports/cyclic-module-package-fp/true-negative/CyclicImport.qlref b/python/ql/test/query-tests/Imports/cyclic-module-package-fp/true-negative/CyclicImport.qlref
index 814bba9fad6..082797c9226 100644
--- a/python/ql/test/query-tests/Imports/cyclic-module-package-fp/true-negative/CyclicImport.qlref
+++ b/python/ql/test/query-tests/Imports/cyclic-module-package-fp/true-negative/CyclicImport.qlref
@@ -1 +1,2 @@
-Imports/CyclicImport.ql
\ No newline at end of file
+query: Imports/CyclicImport.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Imports/cyclic-module-package-fp/true-negative/ModuleLevelCyclicImport.qlref b/python/ql/test/query-tests/Imports/cyclic-module-package-fp/true-negative/ModuleLevelCyclicImport.qlref
index 5119f8fdaae..e0e35483fed 100644
--- a/python/ql/test/query-tests/Imports/cyclic-module-package-fp/true-negative/ModuleLevelCyclicImport.qlref
+++ b/python/ql/test/query-tests/Imports/cyclic-module-package-fp/true-negative/ModuleLevelCyclicImport.qlref
@@ -1 +1,2 @@
-Imports/ModuleLevelCyclicImport.ql
\ No newline at end of file
+query: Imports/ModuleLevelCyclicImport.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Imports/cyclic-module/CyclicImport.qlref b/python/ql/test/query-tests/Imports/cyclic-module/CyclicImport.qlref
index 814bba9fad6..082797c9226 100644
--- a/python/ql/test/query-tests/Imports/cyclic-module/CyclicImport.qlref
+++ b/python/ql/test/query-tests/Imports/cyclic-module/CyclicImport.qlref
@@ -1 +1,2 @@
-Imports/CyclicImport.ql
\ No newline at end of file
+query: Imports/CyclicImport.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Imports/cyclic-module/ModuleLevelCyclicImport.qlref b/python/ql/test/query-tests/Imports/cyclic-module/ModuleLevelCyclicImport.qlref
index 5119f8fdaae..e0e35483fed 100644
--- a/python/ql/test/query-tests/Imports/cyclic-module/ModuleLevelCyclicImport.qlref
+++ b/python/ql/test/query-tests/Imports/cyclic-module/ModuleLevelCyclicImport.qlref
@@ -1 +1,2 @@
-Imports/ModuleLevelCyclicImport.ql
\ No newline at end of file
+query: Imports/ModuleLevelCyclicImport.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Imports/cyclic-module/module1.py b/python/ql/test/query-tests/Imports/cyclic-module/module1.py
index 55ef075e9e6..e17ac87cdca 100644
--- a/python/ql/test/query-tests/Imports/cyclic-module/module1.py
+++ b/python/ql/test/query-tests/Imports/cyclic-module/module1.py
@@ -1,20 +1,20 @@
# potentially crashing cycles
import module2
-import module3
+import module3 # $ Alert[py/cyclic-import]
-a1 = module2.a2
+a1 = module2.a2 # $ Alert[py/unsafe-cyclic-import]
b1 = 2
# bad style cycles
-import module4
+import module4 # $ Alert[py/cyclic-import]
def foo():
- import module5
+ import module5 # $ Alert[py/cyclic-import]
# okay, because some of the cycle is not top level
-import module6
+import module6 # $ Alert[py/cyclic-import]
# OK because this import occurs after relevant definition (a1)
-import module8
+import module8 # $ Alert[py/cyclic-import]
#OK because cycle is guarded by `if False:`
from module10 import x
diff --git a/python/ql/test/query-tests/Imports/cyclic-module/module2.py b/python/ql/test/query-tests/Imports/cyclic-module/module2.py
index 333b8516adb..81899e72e56 100644
--- a/python/ql/test/query-tests/Imports/cyclic-module/module2.py
+++ b/python/ql/test/query-tests/Imports/cyclic-module/module2.py
@@ -1,4 +1,4 @@
import module1
# direct use
-a2 = module1.a1
\ No newline at end of file
+a2 = module1.a1 # $ Alert[py/unsafe-cyclic-import]
\ No newline at end of file
diff --git a/python/ql/test/query-tests/Imports/cyclic-module/module3.py b/python/ql/test/query-tests/Imports/cyclic-module/module3.py
index 2180fb54a28..dd391cfcf5a 100644
--- a/python/ql/test/query-tests/Imports/cyclic-module/module3.py
+++ b/python/ql/test/query-tests/Imports/cyclic-module/module3.py
@@ -1,2 +1,2 @@
# use via import member
-from module1 import a1
\ No newline at end of file
+from module1 import a1 # $ Alert[py/unsafe-cyclic-import]
\ No newline at end of file
diff --git a/python/ql/test/query-tests/Imports/cyclic-module/module4.py b/python/ql/test/query-tests/Imports/cyclic-module/module4.py
index 65db406bb45..790e92121d5 100644
--- a/python/ql/test/query-tests/Imports/cyclic-module/module4.py
+++ b/python/ql/test/query-tests/Imports/cyclic-module/module4.py
@@ -1 +1 @@
-import module1
\ No newline at end of file
+import module1 # $ Alert[py/cyclic-import]
\ No newline at end of file
diff --git a/python/ql/test/query-tests/Imports/cyclic-module/module5.py b/python/ql/test/query-tests/Imports/cyclic-module/module5.py
index 65db406bb45..790e92121d5 100644
--- a/python/ql/test/query-tests/Imports/cyclic-module/module5.py
+++ b/python/ql/test/query-tests/Imports/cyclic-module/module5.py
@@ -1 +1 @@
-import module1
\ No newline at end of file
+import module1 # $ Alert[py/cyclic-import]
\ No newline at end of file
diff --git a/python/ql/test/query-tests/Imports/cyclic-module/module6.py b/python/ql/test/query-tests/Imports/cyclic-module/module6.py
index 5a5fcd149ac..df0376aceaa 100644
--- a/python/ql/test/query-tests/Imports/cyclic-module/module6.py
+++ b/python/ql/test/query-tests/Imports/cyclic-module/module6.py
@@ -1,2 +1,2 @@
def foo():
- import module7
\ No newline at end of file
+ import module7 # $ Alert[py/cyclic-import]
\ No newline at end of file
diff --git a/python/ql/test/query-tests/Imports/cyclic-module/module7.py b/python/ql/test/query-tests/Imports/cyclic-module/module7.py
index d0b18ba5894..6a961467bad 100644
--- a/python/ql/test/query-tests/Imports/cyclic-module/module7.py
+++ b/python/ql/test/query-tests/Imports/cyclic-module/module7.py
@@ -1 +1 @@
-from module1 import a1
\ No newline at end of file
+from module1 import a1 # $ Alert[py/cyclic-import]
\ No newline at end of file
diff --git a/python/ql/test/query-tests/Imports/cyclic-module/module8.py b/python/ql/test/query-tests/Imports/cyclic-module/module8.py
index 185ee214da8..8117f9a6f9c 100644
--- a/python/ql/test/query-tests/Imports/cyclic-module/module8.py
+++ b/python/ql/test/query-tests/Imports/cyclic-module/module8.py
@@ -1,4 +1,4 @@
-import module1
+import module1 # $ Alert[py/cyclic-import]
class Foo(object):
a = module1.a1
\ No newline at end of file
diff --git a/python/ql/test/query-tests/Imports/cyclic-module/module9.py b/python/ql/test/query-tests/Imports/cyclic-module/module9.py
index 06ab5b93305..b8dfb4e10a6 100644
--- a/python/ql/test/query-tests/Imports/cyclic-module/module9.py
+++ b/python/ql/test/query-tests/Imports/cyclic-module/module9.py
@@ -1,6 +1,6 @@
x = 1
-import main
+import main # $ Alert[py/cyclic-import]
y = 2
\ No newline at end of file
diff --git a/python/ql/test/query-tests/Imports/deprecated/DeprecatedModule.qlref b/python/ql/test/query-tests/Imports/deprecated/DeprecatedModule.qlref
index 9f87b11d807..93ed1e7b4be 100644
--- a/python/ql/test/query-tests/Imports/deprecated/DeprecatedModule.qlref
+++ b/python/ql/test/query-tests/Imports/deprecated/DeprecatedModule.qlref
@@ -1 +1,2 @@
-Imports/DeprecatedModule.ql
+query: Imports/DeprecatedModule.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Imports/deprecated/test.py b/python/ql/test/query-tests/Imports/deprecated/test.py
index ce70d29794e..6cf11feb782 100644
--- a/python/ql/test/query-tests/Imports/deprecated/test.py
+++ b/python/ql/test/query-tests/Imports/deprecated/test.py
@@ -1,11 +1,11 @@
# Some deprecated modules
-import rfc822
-import posixfile
+import rfc822 # $ Alert
+import posixfile # $ Alert
# We should only report a bad import once
class Foo(object):
def foo(self):
- import md5
+ import md5 # $ Alert
# Backwards compatible code, should not report
try:
diff --git a/python/ql/test/query-tests/Imports/general/FromImportOfMutableAttribute.qlref b/python/ql/test/query-tests/Imports/general/FromImportOfMutableAttribute.qlref
index 9353115309f..302bb0895a6 100644
--- a/python/ql/test/query-tests/Imports/general/FromImportOfMutableAttribute.qlref
+++ b/python/ql/test/query-tests/Imports/general/FromImportOfMutableAttribute.qlref
@@ -1 +1,2 @@
-Imports/FromImportOfMutableAttribute.ql
\ No newline at end of file
+query: Imports/FromImportOfMutableAttribute.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Imports/general/ImportShadowedByLoopVar.qlref b/python/ql/test/query-tests/Imports/general/ImportShadowedByLoopVar.qlref
index 3844f21922f..d5b4aaa1693 100644
--- a/python/ql/test/query-tests/Imports/general/ImportShadowedByLoopVar.qlref
+++ b/python/ql/test/query-tests/Imports/general/ImportShadowedByLoopVar.qlref
@@ -1 +1,2 @@
-Imports/ImportShadowedByLoopVar.ql
\ No newline at end of file
+query: Imports/ImportShadowedByLoopVar.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Imports/general/ImportStarUsed.qlref b/python/ql/test/query-tests/Imports/general/ImportStarUsed.qlref
index 35f8bff3e5f..099627be88c 100644
--- a/python/ql/test/query-tests/Imports/general/ImportStarUsed.qlref
+++ b/python/ql/test/query-tests/Imports/general/ImportStarUsed.qlref
@@ -1 +1,2 @@
-Imports/ImportStarUsed.ql
\ No newline at end of file
+query: Imports/ImportStarUsed.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Imports/general/Imports.qlref b/python/ql/test/query-tests/Imports/general/Imports.qlref
index 6bcdb2d9b5f..926c62f0a41 100644
--- a/python/ql/test/query-tests/Imports/general/Imports.qlref
+++ b/python/ql/test/query-tests/Imports/general/Imports.qlref
@@ -1 +1,2 @@
-Imports/Imports.ql
+query: Imports/Imports.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Imports/general/MultipleImport.qlref b/python/ql/test/query-tests/Imports/general/MultipleImport.qlref
index a4d2195b688..7826fb7e33c 100644
--- a/python/ql/test/query-tests/Imports/general/MultipleImport.qlref
+++ b/python/ql/test/query-tests/Imports/general/MultipleImport.qlref
@@ -1 +1,2 @@
-Imports/MultipleImports.ql
+query: Imports/MultipleImports.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Imports/general/UnintentionalImport.qlref b/python/ql/test/query-tests/Imports/general/UnintentionalImport.qlref
index 4f1b985d5c2..0ea9a54298f 100644
--- a/python/ql/test/query-tests/Imports/general/UnintentionalImport.qlref
+++ b/python/ql/test/query-tests/Imports/general/UnintentionalImport.qlref
@@ -1 +1,2 @@
-Imports/UnintentionalImport.ql
+query: Imports/UnintentionalImport.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Imports/general/imports_mutable.py b/python/ql/test/query-tests/Imports/general/imports_mutable.py
index 0519a2071d8..91efefc7e9f 100644
--- a/python/ql/test/query-tests/Imports/general/imports_mutable.py
+++ b/python/ql/test/query-tests/Imports/general/imports_mutable.py
@@ -1,4 +1,4 @@
-from mutable_attr import x, y
+from mutable_attr import x, y # $ Alert[py/import-of-mutable-attribute]
def f():
print(x)
diff --git a/python/ql/test/query-tests/Imports/general/imports_test.py b/python/ql/test/query-tests/Imports/general/imports_test.py
index 4b51f8254fc..8a4faf16a34 100644
--- a/python/ql/test/query-tests/Imports/general/imports_test.py
+++ b/python/ql/test/query-tests/Imports/general/imports_test.py
@@ -1,5 +1,5 @@
#Multiple imports on a single line
-import module1, module2
+import module1, module2 # $ Alert[py/multiple-imports-on-line]
#Cyclic import
@@ -13,13 +13,13 @@ import top_level_cycle
import module
-for module in range(10):
+for module in range(10): # $ Alert[py/import-shadowed-loop-variable]
print(module)
#Import * used
-from module import *
-from module_without_all import *
+from module import * # $ Alert[py/import-star-used]
+from module_without_all import * # $ Alert[py/import-star-used] Alert[py/polluting-import]
#Unused import
@@ -30,8 +30,8 @@ module1.func
func1
#Duplicate import
-import module1
-import module2
+import module1 # $ Alert[py/repeated-import]
+import module2 # $ Alert[py/repeated-import]
#OK -- Import used in epytext documentation.
import used_in_docs
@@ -62,4 +62,4 @@ import module1 as different
different
# FP reported in https://github.com/github/codeql/issues/4003
-from module_that_does_not_exist import *
+from module_that_does_not_exist import * # $ Alert[py/import-star-used]
diff --git a/python/ql/test/query-tests/Imports/unused/UnusedImport.qlref b/python/ql/test/query-tests/Imports/unused/UnusedImport.qlref
index e6bb7ab44cb..103f075bb14 100644
--- a/python/ql/test/query-tests/Imports/unused/UnusedImport.qlref
+++ b/python/ql/test/query-tests/Imports/unused/UnusedImport.qlref
@@ -1 +1,2 @@
-Imports/UnusedImport.ql
+query: Imports/UnusedImport.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Imports/unused/import_structure_1.py b/python/ql/test/query-tests/Imports/unused/import_structure_1.py
index a76fe99f12c..3afada1956b 100644
--- a/python/ql/test/query-tests/Imports/unused/import_structure_1.py
+++ b/python/ql/test/query-tests/Imports/unused/import_structure_1.py
@@ -2,7 +2,7 @@
# lines
from typing import Optional
-from unknown import foo, bar
+from unknown import foo, bar # $ Alert
var: Optional['foo'] = None
diff --git a/python/ql/test/query-tests/Imports/unused/import_structure_2.py b/python/ql/test/query-tests/Imports/unused/import_structure_2.py
index 90d4255ba39..01db62d54f8 100644
--- a/python/ql/test/query-tests/Imports/unused/import_structure_2.py
+++ b/python/ql/test/query-tests/Imports/unused/import_structure_2.py
@@ -3,6 +3,6 @@
from typing import Optional
from unknown import foo
-from unknown import bar
+from unknown import bar # $ Alert
var: Optional['foo'] = None
diff --git a/python/ql/test/query-tests/Imports/unused/imports_test.py b/python/ql/test/query-tests/Imports/unused/imports_test.py
index 71363235987..e57d23cc2bb 100644
--- a/python/ql/test/query-tests/Imports/unused/imports_test.py
+++ b/python/ql/test/query-tests/Imports/unused/imports_test.py
@@ -1,13 +1,13 @@
#Multiple imports on a single line
-import module1, module2
+import module1, module2 # $ Alert
#Cyclic import
-import cycle
+import cycle # $ Alert
#Top level cyclic import
-import top_level_cycle
+import top_level_cycle # $ Alert
#Import shadowed by loop variable
@@ -24,14 +24,14 @@ from module_without_all import *
#Unused import
from module2 import func1
-from module2 import func2
+from module2 import func2 # $ Alert
module1.func
func1
#Duplicate import
import module1
-import module2
+import module2 # $ Alert
#OK -- Import used in epytext documentation.
import used_in_docs
@@ -113,6 +113,6 @@ def baz() -> Optional['subexpression_return_type']:
pass
-from pytest_fixtures import not_a_fixture # BAD
+from pytest_fixtures import not_a_fixture # BAD # $ Alert
from pytest_fixtures import fixture, wrapped_fixture # GOOD (pytest fixtures are used implicitly by pytest)
from pytest_fixtures import session_fixture, wrapped_autouse_fixture # GOOD (pytest fixtures are used implicitly by pytest)
diff --git a/python/ql/test/query-tests/Lexical/ToDoComment/ToDoComment.qlref b/python/ql/test/query-tests/Lexical/ToDoComment/ToDoComment.qlref
index 4568a99f388..49cef25c9fd 100644
--- a/python/ql/test/query-tests/Lexical/ToDoComment/ToDoComment.qlref
+++ b/python/ql/test/query-tests/Lexical/ToDoComment/ToDoComment.qlref
@@ -1 +1,2 @@
-Lexical/ToDoComment.ql
\ No newline at end of file
+query: Lexical/ToDoComment.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Lexical/ToDoComment/todo.py b/python/ql/test/query-tests/Lexical/ToDoComment/todo.py
index 5e02882924b..e29370ad327 100644
--- a/python/ql/test/query-tests/Lexical/ToDoComment/todo.py
+++ b/python/ql/test/query-tests/Lexical/ToDoComment/todo.py
@@ -1 +1 @@
-# TO DO -- (Nothing "to do" -- this is a test for TO DO comments)
+# TO DO -- (Nothing "to do" -- this is a test for TO DO comments) # $ Alert
diff --git a/python/ql/test/query-tests/Lexical/commented_out_code/CommentedOutCode.qlref b/python/ql/test/query-tests/Lexical/commented_out_code/CommentedOutCode.qlref
index 6fe55e0fa94..39456a2013e 100644
--- a/python/ql/test/query-tests/Lexical/commented_out_code/CommentedOutCode.qlref
+++ b/python/ql/test/query-tests/Lexical/commented_out_code/CommentedOutCode.qlref
@@ -1 +1,2 @@
-Lexical/CommentedOutCode.ql
+query: Lexical/CommentedOutCode.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Lexical/commented_out_code/FCommentedOutCode.qlref b/python/ql/test/query-tests/Lexical/commented_out_code/FCommentedOutCode.qlref
index 2776efbcfd3..cb0c813f009 100644
--- a/python/ql/test/query-tests/Lexical/commented_out_code/FCommentedOutCode.qlref
+++ b/python/ql/test/query-tests/Lexical/commented_out_code/FCommentedOutCode.qlref
@@ -1 +1 @@
-Lexical/FCommentedOutCode.ql
+query: Lexical/FCommentedOutCode.ql
diff --git a/python/ql/test/query-tests/Lexical/commented_out_code/test.py b/python/ql/test/query-tests/Lexical/commented_out_code/test.py
index 067855b6744..685a2080f6c 100644
--- a/python/ql/test/query-tests/Lexical/commented_out_code/test.py
+++ b/python/ql/test/query-tests/Lexical/commented_out_code/test.py
@@ -13,7 +13,7 @@ def f(x):
if x:
do_something()
#else:
- # do_something_else()
+ # do_something_else() # $ Alert
# Some non-code comments.
# Space immediately after scope start and between functions.
@@ -69,7 +69,7 @@ def f(x):
#
#
#def m():
-# pass
+# pass # $ Alert
#
#
#
@@ -82,7 +82,7 @@ some_code_to_break_up_comments()
#except Exception:
# pass
#except:
-# pass
+# pass # $ Alert
def a_function_to_break_up_comments():
pass
diff --git a/python/ql/test/query-tests/Metrics/cyclo/CyclomaticComplexity.qlref b/python/ql/test/query-tests/Metrics/cyclo/CyclomaticComplexity.qlref
index c74ae215bb4..8e150c5a5c8 100644
--- a/python/ql/test/query-tests/Metrics/cyclo/CyclomaticComplexity.qlref
+++ b/python/ql/test/query-tests/Metrics/cyclo/CyclomaticComplexity.qlref
@@ -1 +1 @@
-Metrics/CyclomaticComplexity.ql
+query: Metrics/CyclomaticComplexity.ql
diff --git a/python/ql/test/query-tests/Metrics/functions/FunctionStatementNestingDepth.qlref b/python/ql/test/query-tests/Metrics/functions/FunctionStatementNestingDepth.qlref
index 797f223792f..5be0496cf08 100644
--- a/python/ql/test/query-tests/Metrics/functions/FunctionStatementNestingDepth.qlref
+++ b/python/ql/test/query-tests/Metrics/functions/FunctionStatementNestingDepth.qlref
@@ -1 +1 @@
-Metrics/FunctionStatementNestingDepth.ql
\ No newline at end of file
+query: Metrics/FunctionStatementNestingDepth.ql
diff --git a/python/ql/test/query-tests/Metrics/imports/DirectImports.qlref b/python/ql/test/query-tests/Metrics/imports/DirectImports.qlref
index 84fe2dc5805..0878b889263 100644
--- a/python/ql/test/query-tests/Metrics/imports/DirectImports.qlref
+++ b/python/ql/test/query-tests/Metrics/imports/DirectImports.qlref
@@ -1 +1 @@
-Metrics/DirectImports.ql
+query: Metrics/DirectImports.ql
diff --git a/python/ql/test/query-tests/Metrics/imports/TransitiveImports.qlref b/python/ql/test/query-tests/Metrics/imports/TransitiveImports.qlref
index 1bacdce45c2..35e369b89b4 100644
--- a/python/ql/test/query-tests/Metrics/imports/TransitiveImports.qlref
+++ b/python/ql/test/query-tests/Metrics/imports/TransitiveImports.qlref
@@ -1 +1 @@
-Metrics/TransitiveImports.ql
\ No newline at end of file
+query: Metrics/TransitiveImports.ql
diff --git a/python/ql/test/query-tests/Metrics/lines/CommentRatio.qlref b/python/ql/test/query-tests/Metrics/lines/CommentRatio.qlref
index 9c3179ac503..a8be2d84cc5 100644
--- a/python/ql/test/query-tests/Metrics/lines/CommentRatio.qlref
+++ b/python/ql/test/query-tests/Metrics/lines/CommentRatio.qlref
@@ -1 +1 @@
-Metrics/CommentRatio.ql
+query: Metrics/CommentRatio.ql
diff --git a/python/ql/test/query-tests/Metrics/lines/FLinesOfCode.qlref b/python/ql/test/query-tests/Metrics/lines/FLinesOfCode.qlref
index 2ac69b8f67a..6a2c24b94b1 100644
--- a/python/ql/test/query-tests/Metrics/lines/FLinesOfCode.qlref
+++ b/python/ql/test/query-tests/Metrics/lines/FLinesOfCode.qlref
@@ -1 +1 @@
-Metrics/FLinesOfCode.ql
+query: Metrics/FLinesOfCode.ql
diff --git a/python/ql/test/query-tests/Metrics/ratios/CommentRatio.qlref b/python/ql/test/query-tests/Metrics/ratios/CommentRatio.qlref
index dc273e16982..a8be2d84cc5 100644
--- a/python/ql/test/query-tests/Metrics/ratios/CommentRatio.qlref
+++ b/python/ql/test/query-tests/Metrics/ratios/CommentRatio.qlref
@@ -1 +1 @@
-Metrics/CommentRatio.ql
\ No newline at end of file
+query: Metrics/CommentRatio.ql
diff --git a/python/ql/test/query-tests/Metrics/ratios/DocStringRatio.qlref b/python/ql/test/query-tests/Metrics/ratios/DocStringRatio.qlref
index ec66c5cdc83..c8c5812818f 100644
--- a/python/ql/test/query-tests/Metrics/ratios/DocStringRatio.qlref
+++ b/python/ql/test/query-tests/Metrics/ratios/DocStringRatio.qlref
@@ -1 +1 @@
-Metrics/DocStringRatio.ql
\ No newline at end of file
+query: Metrics/DocStringRatio.ql
diff --git a/python/ql/test/query-tests/Metrics/tests/FNumberOfTests.qlref b/python/ql/test/query-tests/Metrics/tests/FNumberOfTests.qlref
index e7301c3b230..46d66e54987 100644
--- a/python/ql/test/query-tests/Metrics/tests/FNumberOfTests.qlref
+++ b/python/ql/test/query-tests/Metrics/tests/FNumberOfTests.qlref
@@ -1 +1 @@
-Metrics/FNumberOfTests.ql
\ No newline at end of file
+query: Metrics/FNumberOfTests.ql
diff --git a/python/ql/test/query-tests/Security/CWE-020-CookieInjection/CookieInjection.expected b/python/ql/test/query-tests/Security/CWE-020-CookieInjection/CookieInjection.expected
index cf3a06ac7c8..6e9c8ff47dc 100644
--- a/python/ql/test/query-tests/Security/CWE-020-CookieInjection/CookieInjection.expected
+++ b/python/ql/test/query-tests/Security/CWE-020-CookieInjection/CookieInjection.expected
@@ -1,3 +1,7 @@
+#select
+| django_tests.py:6:21:6:43 | ControlFlowNode for Attribute() | django_tests.py:4:25:4:31 | ControlFlowNode for request | django_tests.py:6:21:6:43 | ControlFlowNode for Attribute() | Cookie is constructed from a $@. | django_tests.py:4:25:4:31 | ControlFlowNode for request | user-supplied input |
+| django_tests.py:7:21:7:44 | ControlFlowNode for Attribute() | django_tests.py:4:25:4:31 | ControlFlowNode for request | django_tests.py:7:21:7:44 | ControlFlowNode for Attribute() | Cookie is constructed from a $@. | django_tests.py:4:25:4:31 | ControlFlowNode for request | user-supplied input |
+| django_tests.py:13:30:13:100 | ControlFlowNode for Fstring | django_tests.py:11:26:11:32 | ControlFlowNode for request | django_tests.py:13:30:13:100 | ControlFlowNode for Fstring | Cookie is constructed from a $@. | django_tests.py:11:26:11:32 | ControlFlowNode for request | user-supplied input |
edges
| django_tests.py:4:25:4:31 | ControlFlowNode for request | django_tests.py:6:21:6:31 | ControlFlowNode for Attribute | provenance | AdditionalTaintStep |
| django_tests.py:4:25:4:31 | ControlFlowNode for request | django_tests.py:7:21:7:31 | ControlFlowNode for Attribute | provenance | AdditionalTaintStep |
@@ -22,7 +26,3 @@ nodes
| django_tests.py:13:59:13:69 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| django_tests.py:13:59:13:82 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
subpaths
-#select
-| django_tests.py:6:21:6:43 | ControlFlowNode for Attribute() | django_tests.py:4:25:4:31 | ControlFlowNode for request | django_tests.py:6:21:6:43 | ControlFlowNode for Attribute() | Cookie is constructed from a $@. | django_tests.py:4:25:4:31 | ControlFlowNode for request | user-supplied input |
-| django_tests.py:7:21:7:44 | ControlFlowNode for Attribute() | django_tests.py:4:25:4:31 | ControlFlowNode for request | django_tests.py:7:21:7:44 | ControlFlowNode for Attribute() | Cookie is constructed from a $@. | django_tests.py:4:25:4:31 | ControlFlowNode for request | user-supplied input |
-| django_tests.py:13:30:13:100 | ControlFlowNode for Fstring | django_tests.py:11:26:11:32 | ControlFlowNode for request | django_tests.py:13:30:13:100 | ControlFlowNode for Fstring | Cookie is constructed from a $@. | django_tests.py:11:26:11:32 | ControlFlowNode for request | user-supplied input |
diff --git a/python/ql/test/query-tests/Security/CWE-020-CookieInjection/CookieInjection.qlref b/python/ql/test/query-tests/Security/CWE-020-CookieInjection/CookieInjection.qlref
index a405c564b1b..788c1b424ff 100644
--- a/python/ql/test/query-tests/Security/CWE-020-CookieInjection/CookieInjection.qlref
+++ b/python/ql/test/query-tests/Security/CWE-020-CookieInjection/CookieInjection.qlref
@@ -1 +1,2 @@
-Security/CWE-020/CookieInjection.ql
\ No newline at end of file
+query: Security/CWE-020/CookieInjection.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Security/CWE-020-CookieInjection/django_tests.py b/python/ql/test/query-tests/Security/CWE-020-CookieInjection/django_tests.py
index e070f5cab82..b016f98dc83 100644
--- a/python/ql/test/query-tests/Security/CWE-020-CookieInjection/django_tests.py
+++ b/python/ql/test/query-tests/Security/CWE-020-CookieInjection/django_tests.py
@@ -1,16 +1,16 @@
import django.http
from django.urls import path
-def django_response_bad(request):
+def django_response_bad(request): # $ Source
resp = django.http.HttpResponse()
- resp.set_cookie(request.GET.get("name"), # BAD: Cookie is constructed from user input
- request.GET.get("value"))
+ resp.set_cookie(request.GET.get("name"), # BAD: Cookie is constructed from user input # $ Alert
+ request.GET.get("value")) # $ Alert
return resp
-def django_response_bad2(request):
+def django_response_bad2(request): # $ Source
response = django.http.HttpResponse()
- response['Set-Cookie'] = f"{request.GET.get('name')}={request.GET.get('value')}; SameSite=None;" # BAD: Cookie header is constructed from user input.
+ response['Set-Cookie'] = f"{request.GET.get('name')}={request.GET.get('value')}; SameSite=None;" # BAD: Cookie header is constructed from user input. # $ Alert
return response
# fake setup, you can't actually run this
diff --git a/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.qlref b/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.qlref
index c91bf44f815..34ac0b64014 100644
--- a/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.qlref
+++ b/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.qlref
@@ -1 +1 @@
-Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.ql
+query: Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.ql
diff --git a/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.expected b/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.expected
index 7f83ceae8fe..69039d12c4d 100644
--- a/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.expected
+++ b/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.expected
@@ -1,3 +1,10 @@
+#select
+| test.py:15:36:15:39 | ControlFlowNode for data | test.py:5:26:5:32 | ControlFlowNode for ImportMember | test.py:15:36:15:39 | ControlFlowNode for data | Call to hmac.new [position 1] with untrusted data from $@. | test.py:5:26:5:32 | ControlFlowNode for ImportMember | ControlFlowNode for ImportMember |
+| test.py:25:44:25:47 | ControlFlowNode for data | test.py:5:26:5:32 | ControlFlowNode for ImportMember | test.py:25:44:25:47 | ControlFlowNode for data | Call to hmac.new [keyword msg] with untrusted data from $@. | test.py:5:26:5:32 | ControlFlowNode for ImportMember | ControlFlowNode for ImportMember |
+| test.py:35:10:35:13 | ControlFlowNode for data | test.py:5:26:5:32 | ControlFlowNode for ImportMember | test.py:35:10:35:13 | ControlFlowNode for data | Call to unknown.lib.func [position 0] with untrusted data from $@. | test.py:5:26:5:32 | ControlFlowNode for ImportMember | ControlFlowNode for ImportMember |
+| test.py:36:13:36:16 | ControlFlowNode for data | test.py:5:26:5:32 | ControlFlowNode for ImportMember | test.py:36:13:36:16 | ControlFlowNode for data | Call to unknown.lib.func [keyword kw] with untrusted data from $@. | test.py:5:26:5:32 | ControlFlowNode for ImportMember | ControlFlowNode for ImportMember |
+| test.py:43:22:43:25 | ControlFlowNode for data | test.py:5:26:5:32 | ControlFlowNode for ImportMember | test.py:43:22:43:25 | ControlFlowNode for data | Call to unknown.lib.func [position 0] with untrusted data from $@. | test.py:5:26:5:32 | ControlFlowNode for ImportMember | ControlFlowNode for ImportMember |
+| test.py:44:25:44:28 | ControlFlowNode for data | test.py:5:26:5:32 | ControlFlowNode for ImportMember | test.py:44:25:44:28 | ControlFlowNode for data | Call to unknown.lib.func [keyword kw] with untrusted data from $@. | test.py:5:26:5:32 | ControlFlowNode for ImportMember | ControlFlowNode for ImportMember |
edges
| test.py:5:26:5:32 | ControlFlowNode for ImportMember | test.py:5:26:5:32 | ControlFlowNode for request | provenance | |
| test.py:5:26:5:32 | ControlFlowNode for request | test.py:13:16:13:22 | ControlFlowNode for request | provenance | |
@@ -68,10 +75,3 @@ nodes
| test.py:54:12:54:35 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| test.py:55:17:55:20 | ControlFlowNode for data | semmle.label | ControlFlowNode for data |
subpaths
-#select
-| test.py:15:36:15:39 | ControlFlowNode for data | test.py:5:26:5:32 | ControlFlowNode for ImportMember | test.py:15:36:15:39 | ControlFlowNode for data | Call to hmac.new [position 1] with untrusted data from $@. | test.py:5:26:5:32 | ControlFlowNode for ImportMember | ControlFlowNode for ImportMember |
-| test.py:25:44:25:47 | ControlFlowNode for data | test.py:5:26:5:32 | ControlFlowNode for ImportMember | test.py:25:44:25:47 | ControlFlowNode for data | Call to hmac.new [keyword msg] with untrusted data from $@. | test.py:5:26:5:32 | ControlFlowNode for ImportMember | ControlFlowNode for ImportMember |
-| test.py:35:10:35:13 | ControlFlowNode for data | test.py:5:26:5:32 | ControlFlowNode for ImportMember | test.py:35:10:35:13 | ControlFlowNode for data | Call to unknown.lib.func [position 0] with untrusted data from $@. | test.py:5:26:5:32 | ControlFlowNode for ImportMember | ControlFlowNode for ImportMember |
-| test.py:36:13:36:16 | ControlFlowNode for data | test.py:5:26:5:32 | ControlFlowNode for ImportMember | test.py:36:13:36:16 | ControlFlowNode for data | Call to unknown.lib.func [keyword kw] with untrusted data from $@. | test.py:5:26:5:32 | ControlFlowNode for ImportMember | ControlFlowNode for ImportMember |
-| test.py:43:22:43:25 | ControlFlowNode for data | test.py:5:26:5:32 | ControlFlowNode for ImportMember | test.py:43:22:43:25 | ControlFlowNode for data | Call to unknown.lib.func [position 0] with untrusted data from $@. | test.py:5:26:5:32 | ControlFlowNode for ImportMember | ControlFlowNode for ImportMember |
-| test.py:44:25:44:28 | ControlFlowNode for data | test.py:5:26:5:32 | ControlFlowNode for ImportMember | test.py:44:25:44:28 | ControlFlowNode for data | Call to unknown.lib.func [keyword kw] with untrusted data from $@. | test.py:5:26:5:32 | ControlFlowNode for ImportMember | ControlFlowNode for ImportMember |
diff --git a/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.qlref b/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.qlref
index 03c06feeec8..fbacbf2a07a 100644
--- a/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.qlref
+++ b/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.qlref
@@ -1 +1,2 @@
-Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.ql
+query: Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/test.py b/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/test.py
index 18b46298d8a..f2857914c03 100644
--- a/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/test.py
+++ b/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/test.py
@@ -2,7 +2,7 @@ import hashlib
import hmac
import base64
-from flask import Flask, request, make_response
+from flask import Flask, request, make_response # $ Source
app = Flask(__name__)
SECRET_KEY = b"SECRET_KEY"
@@ -12,7 +12,7 @@ SECRET_KEY = b"SECRET_KEY"
def hmac_example():
data_raw = request.args.get("data").encode('utf-8')
data = base64.decodebytes(data_raw)
- my_hmac = hmac.new(SECRET_KEY, data, hashlib.sha256)
+ my_hmac = hmac.new(SECRET_KEY, data, hashlib.sha256) # $ Alert
digest = my_hmac.digest()
print(digest)
return "ok"
@@ -22,7 +22,7 @@ def hmac_example():
def hmac_example2():
data_raw = request.args.get("data").encode('utf-8')
data = base64.decodebytes(data_raw)
- my_hmac = hmac.new(key=SECRET_KEY, msg=data, digestmod=hashlib.sha256)
+ my_hmac = hmac.new(key=SECRET_KEY, msg=data, digestmod=hashlib.sha256) # $ Alert
digest = my_hmac.digest()
print(digest)
return "ok"
@@ -32,16 +32,16 @@ def hmac_example2():
def unknown_lib_1():
from unknown.lib import func
data = request.args.get("data")
- func(data)
- func(kw=data)
+ func(data) # $ Alert
+ func(kw=data) # $ Alert
@app.route("/unknown-lib-2")
def unknown_lib_2():
import unknown.lib
data = request.args.get("data")
- unknown.lib.func(data)
- unknown.lib.func(kw=data)
+ unknown.lib.func(data) # $ Alert
+ unknown.lib.func(kw=data) # $ Alert
def handle_this(arg, application = None):
diff --git a/python/ql/test/query-tests/Security/CWE-020-IncompleteHostnameRegExp/IncompleteHostnameRegExp.qlref b/python/ql/test/query-tests/Security/CWE-020-IncompleteHostnameRegExp/IncompleteHostnameRegExp.qlref
index e818d947252..d1afa385825 100644
--- a/python/ql/test/query-tests/Security/CWE-020-IncompleteHostnameRegExp/IncompleteHostnameRegExp.qlref
+++ b/python/ql/test/query-tests/Security/CWE-020-IncompleteHostnameRegExp/IncompleteHostnameRegExp.qlref
@@ -1 +1,2 @@
-Security/CWE-020/IncompleteHostnameRegExp.ql
\ No newline at end of file
+query: Security/CWE-020/IncompleteHostnameRegExp.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Security/CWE-020-IncompleteHostnameRegExp/hosttest.py b/python/ql/test/query-tests/Security/CWE-020-IncompleteHostnameRegExp/hosttest.py
index ca7f7094a8c..e2e90e65142 100644
--- a/python/ql/test/query-tests/Security/CWE-020-IncompleteHostnameRegExp/hosttest.py
+++ b/python/ql/test/query-tests/Security/CWE-020-IncompleteHostnameRegExp/hosttest.py
@@ -3,7 +3,7 @@ import re
app = Flask(__name__)
-UNSAFE_REGEX = re.compile("(www|beta).example.com/")
+UNSAFE_REGEX = re.compile("(www|beta).example.com/") # $ Alert
SAFE_REGEX = re.compile(r"(www|beta)\.example\.com/")
@app.route('/some/path/bad')
diff --git a/python/ql/test/query-tests/Security/CWE-020-IncompleteUrlSubstringSanitization/IncompleteUrlSubstringSanitization.qlref b/python/ql/test/query-tests/Security/CWE-020-IncompleteUrlSubstringSanitization/IncompleteUrlSubstringSanitization.qlref
index 3fa6794419d..1c4c2382153 100644
--- a/python/ql/test/query-tests/Security/CWE-020-IncompleteUrlSubstringSanitization/IncompleteUrlSubstringSanitization.qlref
+++ b/python/ql/test/query-tests/Security/CWE-020-IncompleteUrlSubstringSanitization/IncompleteUrlSubstringSanitization.qlref
@@ -1 +1,2 @@
-Security/CWE-020/IncompleteUrlSubstringSanitization.ql
\ No newline at end of file
+query: Security/CWE-020/IncompleteUrlSubstringSanitization.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Security/CWE-020-IncompleteUrlSubstringSanitization/urltest.py b/python/ql/test/query-tests/Security/CWE-020-IncompleteUrlSubstringSanitization/urltest.py
index 308b946603b..bc59d83819a 100644
--- a/python/ql/test/query-tests/Security/CWE-020-IncompleteUrlSubstringSanitization/urltest.py
+++ b/python/ql/test/query-tests/Security/CWE-020-IncompleteUrlSubstringSanitization/urltest.py
@@ -6,13 +6,13 @@ app = Flask(__name__)
@app.route('/some/path/bad1')
def unsafe1(request):
target = request.args.get('target', '')
- if "example.com" in target:
+ if "example.com" in target: # $ Alert
return redirect(target)
@app.route('/some/path/bad2')
def unsafe2(request):
target = request.args.get('target', '')
- if target.endswith("example.com"):
+ if target.endswith("example.com"): # $ Alert
return redirect(target)
diff --git a/python/ql/test/query-tests/Security/CWE-020-SuspiciousRegexpRange/OverlyLargeRangeQuery.qlref b/python/ql/test/query-tests/Security/CWE-020-SuspiciousRegexpRange/OverlyLargeRangeQuery.qlref
index 77b5c92707f..c42315c4550 100644
--- a/python/ql/test/query-tests/Security/CWE-020-SuspiciousRegexpRange/OverlyLargeRangeQuery.qlref
+++ b/python/ql/test/query-tests/Security/CWE-020-SuspiciousRegexpRange/OverlyLargeRangeQuery.qlref
@@ -1 +1,2 @@
-Security/CWE-020/OverlyLargeRange.ql
+query: Security/CWE-020/OverlyLargeRange.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Security/CWE-020-SuspiciousRegexpRange/test.py b/python/ql/test/query-tests/Security/CWE-020-SuspiciousRegexpRange/test.py
index 43380ccef0d..d24dcef864d 100644
--- a/python/ql/test/query-tests/Security/CWE-020-SuspiciousRegexpRange/test.py
+++ b/python/ql/test/query-tests/Security/CWE-020-SuspiciousRegexpRange/test.py
@@ -1,10 +1,10 @@
import re
-overlap1 = re.compile(r'^[0-93-5]$') # NOT OK
+overlap1 = re.compile(r'^[0-93-5]$') # NOT OK # $ Alert
-overlap2 = re.compile(r'[A-ZA-z]') # NOT OK
+overlap2 = re.compile(r'[A-ZA-z]') # NOT OK # $ Alert
-isEmpty = re.compile(r'^[z-a]$') # NOT OK
+isEmpty = re.compile(r'^[z-a]$') # NOT OK # $ Alert
isAscii = re.compile(r'^[\x00-\x7F]*$') # OK
@@ -14,18 +14,18 @@ codePoints = re.compile(r'[^\x21-\x7E]|[[\](){}<>/%]') # OK
NON_ALPHANUMERIC_REGEXP = re.compile(r'([^\#-~| |!])') # OK
-smallOverlap = re.compile(r'[0-9a-fA-f]') # NOT OK
+smallOverlap = re.compile(r'[0-9a-fA-f]') # NOT OK # $ Alert
-weirdRange = re.compile(r'[$-`]') # NOT OK
+weirdRange = re.compile(r'[$-`]') # NOT OK # $ Alert
-keywordOperator = re.compile(r'[!\~\*\/%+-<>\^|=&]') # NOT OK
+keywordOperator = re.compile(r'[!\~\*\/%+-<>\^|=&]') # NOT OK # $ Alert
-notYoutube = re.compile(r'youtu\.be\/[a-z1-9.-_]+') # NOT OK
+notYoutube = re.compile(r'youtu\.be\/[a-z1-9.-_]+') # NOT OK # $ Alert
-numberToLetter = re.compile(r'[7-F]') # NOT OK
+numberToLetter = re.compile(r'[7-F]') # NOT OK # $ Alert
-overlapsWithClass1 = re.compile(r'[0-9\d]') # NOT OK
+overlapsWithClass1 = re.compile(r'[0-9\d]') # NOT OK # $ Alert
-overlapsWithClass2 = re.compile(r'[\w,.-?:*+]') # NOT OK
+overlapsWithClass2 = re.compile(r'[\w,.-?:*+]') # NOT OK # $ Alert
-unicodeStuff = re.compile('[\U0001D173-\U0001D17A\U000E0020-\U000E007F\U000e0001]') # NOT OK
\ No newline at end of file
+unicodeStuff = re.compile('[\U0001D173-\U0001D17A\U000E0020-\U000E007F\U000e0001]') # NOT OK # $ Alert
\ No newline at end of file
diff --git a/python/ql/test/query-tests/Security/CWE-022-TarSlip/TarSlip.expected b/python/ql/test/query-tests/Security/CWE-022-TarSlip/TarSlip.expected
index 6f98ea1aae2..abdccddd631 100644
--- a/python/ql/test/query-tests/Security/CWE-022-TarSlip/TarSlip.expected
+++ b/python/ql/test/query-tests/Security/CWE-022-TarSlip/TarSlip.expected
@@ -1,3 +1,13 @@
+#select
+| tarslip.py:15:1:15:3 | ControlFlowNode for tar | tarslip.py:14:7:14:39 | ControlFlowNode for Attribute() | tarslip.py:15:1:15:3 | ControlFlowNode for tar | This file extraction depends on a $@. | tarslip.py:14:7:14:39 | ControlFlowNode for Attribute() | potentially untrusted source |
+| tarslip.py:20:17:20:21 | ControlFlowNode for entry | tarslip.py:18:7:18:39 | ControlFlowNode for Attribute() | tarslip.py:20:17:20:21 | ControlFlowNode for entry | This file extraction depends on a $@. | tarslip.py:18:7:18:39 | ControlFlowNode for Attribute() | potentially untrusted source |
+| tarslip.py:39:17:39:21 | ControlFlowNode for entry | tarslip.py:35:7:35:39 | ControlFlowNode for Attribute() | tarslip.py:39:17:39:21 | ControlFlowNode for entry | This file extraction depends on a $@. | tarslip.py:35:7:35:39 | ControlFlowNode for Attribute() | potentially untrusted source |
+| tarslip.py:43:24:43:26 | ControlFlowNode for tar | tarslip.py:42:7:42:39 | ControlFlowNode for Attribute() | tarslip.py:43:24:43:26 | ControlFlowNode for tar | This file extraction depends on a $@. | tarslip.py:42:7:42:39 | ControlFlowNode for Attribute() | potentially untrusted source |
+| tarslip.py:61:21:61:25 | ControlFlowNode for entry | tarslip.py:58:7:58:39 | ControlFlowNode for Attribute() | tarslip.py:61:21:61:25 | ControlFlowNode for entry | This file extraction depends on a $@. | tarslip.py:58:7:58:39 | ControlFlowNode for Attribute() | potentially untrusted source |
+| tarslip.py:91:1:91:3 | ControlFlowNode for tar | tarslip.py:90:7:90:39 | ControlFlowNode for Attribute() | tarslip.py:91:1:91:3 | ControlFlowNode for tar | This file extraction depends on a $@. | tarslip.py:90:7:90:39 | ControlFlowNode for Attribute() | potentially untrusted source |
+| tarslip.py:96:17:96:21 | ControlFlowNode for entry | tarslip.py:94:7:94:39 | ControlFlowNode for Attribute() | tarslip.py:96:17:96:21 | ControlFlowNode for entry | This file extraction depends on a $@. | tarslip.py:94:7:94:39 | ControlFlowNode for Attribute() | potentially untrusted source |
+| tarslip.py:110:1:110:3 | ControlFlowNode for tar | tarslip.py:109:7:109:39 | ControlFlowNode for Attribute() | tarslip.py:110:1:110:3 | ControlFlowNode for tar | This file extraction depends on a $@. | tarslip.py:109:7:109:39 | ControlFlowNode for Attribute() | potentially untrusted source |
+| tarslip.py:113:24:113:26 | ControlFlowNode for tar | tarslip.py:112:7:112:39 | ControlFlowNode for Attribute() | tarslip.py:113:24:113:26 | ControlFlowNode for tar | This file extraction depends on a $@. | tarslip.py:112:7:112:39 | ControlFlowNode for Attribute() | potentially untrusted source |
edges
| tarslip.py:14:1:14:3 | ControlFlowNode for tar | tarslip.py:15:1:15:3 | ControlFlowNode for tar | provenance | |
| tarslip.py:14:7:14:39 | ControlFlowNode for Attribute() | tarslip.py:14:1:14:3 | ControlFlowNode for tar | provenance | |
@@ -54,13 +64,3 @@ nodes
| tarslip.py:112:7:112:39 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| tarslip.py:113:24:113:26 | ControlFlowNode for tar | semmle.label | ControlFlowNode for tar |
subpaths
-#select
-| tarslip.py:15:1:15:3 | ControlFlowNode for tar | tarslip.py:14:7:14:39 | ControlFlowNode for Attribute() | tarslip.py:15:1:15:3 | ControlFlowNode for tar | This file extraction depends on a $@. | tarslip.py:14:7:14:39 | ControlFlowNode for Attribute() | potentially untrusted source |
-| tarslip.py:20:17:20:21 | ControlFlowNode for entry | tarslip.py:18:7:18:39 | ControlFlowNode for Attribute() | tarslip.py:20:17:20:21 | ControlFlowNode for entry | This file extraction depends on a $@. | tarslip.py:18:7:18:39 | ControlFlowNode for Attribute() | potentially untrusted source |
-| tarslip.py:39:17:39:21 | ControlFlowNode for entry | tarslip.py:35:7:35:39 | ControlFlowNode for Attribute() | tarslip.py:39:17:39:21 | ControlFlowNode for entry | This file extraction depends on a $@. | tarslip.py:35:7:35:39 | ControlFlowNode for Attribute() | potentially untrusted source |
-| tarslip.py:43:24:43:26 | ControlFlowNode for tar | tarslip.py:42:7:42:39 | ControlFlowNode for Attribute() | tarslip.py:43:24:43:26 | ControlFlowNode for tar | This file extraction depends on a $@. | tarslip.py:42:7:42:39 | ControlFlowNode for Attribute() | potentially untrusted source |
-| tarslip.py:61:21:61:25 | ControlFlowNode for entry | tarslip.py:58:7:58:39 | ControlFlowNode for Attribute() | tarslip.py:61:21:61:25 | ControlFlowNode for entry | This file extraction depends on a $@. | tarslip.py:58:7:58:39 | ControlFlowNode for Attribute() | potentially untrusted source |
-| tarslip.py:91:1:91:3 | ControlFlowNode for tar | tarslip.py:90:7:90:39 | ControlFlowNode for Attribute() | tarslip.py:91:1:91:3 | ControlFlowNode for tar | This file extraction depends on a $@. | tarslip.py:90:7:90:39 | ControlFlowNode for Attribute() | potentially untrusted source |
-| tarslip.py:96:17:96:21 | ControlFlowNode for entry | tarslip.py:94:7:94:39 | ControlFlowNode for Attribute() | tarslip.py:96:17:96:21 | ControlFlowNode for entry | This file extraction depends on a $@. | tarslip.py:94:7:94:39 | ControlFlowNode for Attribute() | potentially untrusted source |
-| tarslip.py:110:1:110:3 | ControlFlowNode for tar | tarslip.py:109:7:109:39 | ControlFlowNode for Attribute() | tarslip.py:110:1:110:3 | ControlFlowNode for tar | This file extraction depends on a $@. | tarslip.py:109:7:109:39 | ControlFlowNode for Attribute() | potentially untrusted source |
-| tarslip.py:113:24:113:26 | ControlFlowNode for tar | tarslip.py:112:7:112:39 | ControlFlowNode for Attribute() | tarslip.py:113:24:113:26 | ControlFlowNode for tar | This file extraction depends on a $@. | tarslip.py:112:7:112:39 | ControlFlowNode for Attribute() | potentially untrusted source |
diff --git a/python/ql/test/query-tests/Security/CWE-022-TarSlip/TarSlip.qlref b/python/ql/test/query-tests/Security/CWE-022-TarSlip/TarSlip.qlref
index cfede0c92b2..c9b6b9f4f06 100644
--- a/python/ql/test/query-tests/Security/CWE-022-TarSlip/TarSlip.qlref
+++ b/python/ql/test/query-tests/Security/CWE-022-TarSlip/TarSlip.qlref
@@ -1 +1,2 @@
-Security/CWE-022/TarSlip.ql
+query: Security/CWE-022/TarSlip.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Security/CWE-022-TarSlip/tarslip.py b/python/ql/test/query-tests/Security/CWE-022-TarSlip/tarslip.py
index 2c06d01adfd..616c93043f7 100644
--- a/python/ql/test/query-tests/Security/CWE-022-TarSlip/tarslip.py
+++ b/python/ql/test/query-tests/Security/CWE-022-TarSlip/tarslip.py
@@ -11,13 +11,13 @@ tar = tarfile.open(safe_filename_tar)
for entry in tar:
tar.extract(entry)
-tar = tarfile.open(unsafe_filename_tar)
-tar.extractall()
+tar = tarfile.open(unsafe_filename_tar) # $ Source
+tar.extractall() # $ Alert
tar.close()
-tar = tarfile.open(unsafe_filename_tar)
+tar = tarfile.open(unsafe_filename_tar) # $ Source
for entry in tar:
- tar.extract(entry)
+ tar.extract(entry) # $ Alert
tar = tarfile.open(safe_filename_tar)
tar.extractall()
@@ -32,15 +32,15 @@ for entry in tar:
tar.extract(entry, "/tmp/unpack/")
#Part Sanitized
-tar = tarfile.open(unsafe_filename_tar)
+tar = tarfile.open(unsafe_filename_tar) # $ Source
for entry in tar:
if ".." in entry.name:
raise ValueError("Illegal tar archive entry")
- tar.extract(entry, "/tmp/unpack/")
+ tar.extract(entry, "/tmp/unpack/") # $ Alert
#Unsanitized members
-tar = tarfile.open(unsafe_filename_tar)
-tar.extractall(members=tar)
+tar = tarfile.open(unsafe_filename_tar) # $ Source
+tar.extractall(members=tar) # $ Alert
#Sanitize members
@@ -55,10 +55,10 @@ tar.extractall(members=safemembers(tar))
# Wrong sanitizer (is missing not)
-tar = tarfile.open(unsafe_filename_tar)
+tar = tarfile.open(unsafe_filename_tar) # $ Source
for entry in tar:
if os.path.isabs(entry.name) or ".." in entry.name:
- tar.extract(entry, "/tmp/unpack/")
+ tar.extract(entry, "/tmp/unpack/") # $ Alert
# OK Sanitized using not
@@ -87,13 +87,13 @@ for entry in tar:
extraction_filter = "fully_trusted"
-tar = tarfile.open(unsafe_filename_tar)
-tar.extractall(filter=extraction_filter) # unsafe
+tar = tarfile.open(unsafe_filename_tar) # $ Source
+tar.extractall(filter=extraction_filter) # unsafe # $ Alert
tar.close()
-tar = tarfile.open(unsafe_filename_tar)
+tar = tarfile.open(unsafe_filename_tar) # $ Source
for entry in tar:
- tar.extract(entry, filter=extraction_filter) # unsafe
+ tar.extract(entry, filter=extraction_filter) # unsafe # $ Alert
extraction_filter = "data"
@@ -106,11 +106,11 @@ for entry in tar:
tar.extract(entry, filter=extraction_filter) # safe
extraction_filter = None
-tar = tarfile.open(unsafe_filename_tar)
-tar.extractall(filter=extraction_filter) # unsafe
+tar = tarfile.open(unsafe_filename_tar) # $ Source
+tar.extractall(filter=extraction_filter) # unsafe # $ Alert
-tar = tarfile.open(unsafe_filename_tar)
-tar.extractall(members=tar, filter=extraction_filter) # unsafe
+tar = tarfile.open(unsafe_filename_tar) # $ Source
+tar.extractall(members=tar, filter=extraction_filter) # unsafe # $ Alert
tar = tarfile.open(unsafe_filename_tar)
tar.extractall(members=safemembers(tar), filter=extraction_filter) # safe -- we assume `safemembers` makes up for the unsafe filter
diff --git a/python/ql/test/query-tests/Security/CWE-074-TemplateInjection/JinjaSsti.py b/python/ql/test/query-tests/Security/CWE-074-TemplateInjection/JinjaSsti.py
index f1fe834e493..0dad4e31f64 100644
--- a/python/ql/test/query-tests/Security/CWE-074-TemplateInjection/JinjaSsti.py
+++ b/python/ql/test/query-tests/Security/CWE-074-TemplateInjection/JinjaSsti.py
@@ -4,21 +4,21 @@ from jinja2 import Template
from jinja2 import Environment, DictLoader, escape
-def a(request):
+def a(request): # $ Source
# Load the template
template = request.GET['template']
- t = Template(template) # BAD: Template constructed from user input
+ t = Template(template) # BAD: Template constructed from user input # $ Alert
name = request.GET['name']
# Render the template with the context data
html = t.render(name=escape(name))
return HttpResponse(html)
-def b(request):
+def b(request): # $ Source
import jinja2
# Load the template
template = request.GET['template']
env = Environment()
- t = env.from_string(template) # BAD: Template constructed from user input
+ t = env.from_string(template) # BAD: Template constructed from user input # $ Alert
name = request.GET['name']
# Render the template with the context data
html = t.render(name=escape(name))
diff --git a/python/ql/test/query-tests/Security/CWE-074-TemplateInjection/TemplateInjection.expected b/python/ql/test/query-tests/Security/CWE-074-TemplateInjection/TemplateInjection.expected
index f9210772839..a4bf57e174c 100644
--- a/python/ql/test/query-tests/Security/CWE-074-TemplateInjection/TemplateInjection.expected
+++ b/python/ql/test/query-tests/Security/CWE-074-TemplateInjection/TemplateInjection.expected
@@ -1,3 +1,6 @@
+#select
+| JinjaSsti.py:10:18:10:25 | ControlFlowNode for template | JinjaSsti.py:7:7:7:13 | ControlFlowNode for request | JinjaSsti.py:10:18:10:25 | ControlFlowNode for template | This template construction depends on a $@. | JinjaSsti.py:7:7:7:13 | ControlFlowNode for request | user-provided value |
+| JinjaSsti.py:21:25:21:32 | ControlFlowNode for template | JinjaSsti.py:16:7:16:13 | ControlFlowNode for request | JinjaSsti.py:21:25:21:32 | ControlFlowNode for template | This template construction depends on a $@. | JinjaSsti.py:16:7:16:13 | ControlFlowNode for request | user-provided value |
edges
| JinjaSsti.py:7:7:7:13 | ControlFlowNode for request | JinjaSsti.py:9:5:9:12 | ControlFlowNode for template | provenance | AdditionalTaintStep |
| JinjaSsti.py:9:5:9:12 | ControlFlowNode for template | JinjaSsti.py:10:18:10:25 | ControlFlowNode for template | provenance | |
@@ -11,6 +14,3 @@ nodes
| JinjaSsti.py:19:5:19:12 | ControlFlowNode for template | semmle.label | ControlFlowNode for template |
| JinjaSsti.py:21:25:21:32 | ControlFlowNode for template | semmle.label | ControlFlowNode for template |
subpaths
-#select
-| JinjaSsti.py:10:18:10:25 | ControlFlowNode for template | JinjaSsti.py:7:7:7:13 | ControlFlowNode for request | JinjaSsti.py:10:18:10:25 | ControlFlowNode for template | This template construction depends on a $@. | JinjaSsti.py:7:7:7:13 | ControlFlowNode for request | user-provided value |
-| JinjaSsti.py:21:25:21:32 | ControlFlowNode for template | JinjaSsti.py:16:7:16:13 | ControlFlowNode for request | JinjaSsti.py:21:25:21:32 | ControlFlowNode for template | This template construction depends on a $@. | JinjaSsti.py:16:7:16:13 | ControlFlowNode for request | user-provided value |
diff --git a/python/ql/test/query-tests/Security/CWE-074-TemplateInjection/TemplateInjection.qlref b/python/ql/test/query-tests/Security/CWE-074-TemplateInjection/TemplateInjection.qlref
index ead6bb469c6..818407e3eb8 100644
--- a/python/ql/test/query-tests/Security/CWE-074-TemplateInjection/TemplateInjection.qlref
+++ b/python/ql/test/query-tests/Security/CWE-074-TemplateInjection/TemplateInjection.qlref
@@ -1 +1,2 @@
-Security/CWE-074/TemplateInjection.ql
\ No newline at end of file
+query: Security/CWE-074/TemplateInjection.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/CommandInjection.expected b/python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/CommandInjection.expected
index 563a0ac74ae..99941d47b28 100644
--- a/python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/CommandInjection.expected
+++ b/python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/CommandInjection.expected
@@ -1,3 +1,13 @@
+#select
+| command_injection.py:19:15:19:27 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:19:15:19:27 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value |
+| command_injection.py:20:15:20:27 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:20:15:20:27 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value |
+| command_injection.py:21:15:21:27 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:21:15:21:27 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value |
+| command_injection.py:23:20:23:32 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:23:20:23:32 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value |
+| command_injection.py:25:19:25:31 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:25:19:25:31 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value |
+| command_injection.py:26:19:26:31 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:26:19:26:31 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value |
+| command_injection.py:27:19:27:31 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:27:19:27:31 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value |
+| command_injection.py:28:19:28:31 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:28:19:28:31 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value |
+| command_injection.py:29:19:29:31 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:29:19:29:31 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value |
edges
| command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:5:26:5:32 | ControlFlowNode for request | provenance | |
| command_injection.py:5:26:5:32 | ControlFlowNode for request | command_injection.py:18:13:18:19 | ControlFlowNode for request | provenance | |
@@ -30,13 +40,3 @@ nodes
| command_injection.py:28:19:28:31 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr |
| command_injection.py:29:19:29:31 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr |
subpaths
-#select
-| command_injection.py:19:15:19:27 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:19:15:19:27 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value |
-| command_injection.py:20:15:20:27 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:20:15:20:27 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value |
-| command_injection.py:21:15:21:27 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:21:15:21:27 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value |
-| command_injection.py:23:20:23:32 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:23:20:23:32 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value |
-| command_injection.py:25:19:25:31 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:25:19:25:31 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value |
-| command_injection.py:26:19:26:31 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:26:19:26:31 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value |
-| command_injection.py:27:19:27:31 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:27:19:27:31 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value |
-| command_injection.py:28:19:28:31 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:28:19:28:31 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value |
-| command_injection.py:29:19:29:31 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:29:19:29:31 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value |
diff --git a/python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/CommandInjection.qlref b/python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/CommandInjection.qlref
index e38b88f2919..8d677af3571 100644
--- a/python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/CommandInjection.qlref
+++ b/python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/CommandInjection.qlref
@@ -1 +1,2 @@
-Security/CWE-078/CommandInjection.ql
+query: Security/CWE-078/CommandInjection.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/command_injection.py b/python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/command_injection.py
index 09dd2bf9716..676215f29d1 100644
--- a/python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/command_injection.py
+++ b/python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/command_injection.py
@@ -2,7 +2,7 @@ import os
import platform
import popen2
-from flask import Flask, request
+from flask import Flask, request # $ Source
app = Flask(__name__)
@@ -16,14 +16,14 @@ def python2_specific():
"""
files = request.args.get("files", "")
- os.popen2("ls " + files)
- os.popen3("ls " + files)
- os.popen4("ls " + files)
+ os.popen2("ls " + files) # $ Alert
+ os.popen3("ls " + files) # $ Alert
+ os.popen4("ls " + files) # $ Alert
- platform.popen("ls " + files)
+ platform.popen("ls " + files) # $ Alert
- popen2.popen2("ls " + files)
- popen2.popen3("ls " + files)
- popen2.popen4("ls " + files)
- popen2.Popen3("ls " + files)
- popen2.Popen4("ls " + files)
+ popen2.popen2("ls " + files) # $ Alert
+ popen2.popen3("ls " + files) # $ Alert
+ popen2.popen4("ls " + files) # $ Alert
+ popen2.Popen3("ls " + files) # $ Alert
+ popen2.Popen4("ls " + files) # $ Alert
diff --git a/python/ql/test/query-tests/Security/CWE-078-CommandInjection/CommandInjection.qlref b/python/ql/test/query-tests/Security/CWE-078-CommandInjection/CommandInjection.qlref
index e38b88f2919..47dd63a884e 100644
--- a/python/ql/test/query-tests/Security/CWE-078-CommandInjection/CommandInjection.qlref
+++ b/python/ql/test/query-tests/Security/CWE-078-CommandInjection/CommandInjection.qlref
@@ -1 +1 @@
-Security/CWE-078/CommandInjection.ql
+query: Security/CWE-078/CommandInjection.ql
diff --git a/python/ql/test/query-tests/Security/CWE-078-UnsafeShellCommandConstruction/UnsafeShellCommandConstruction.qlref b/python/ql/test/query-tests/Security/CWE-078-UnsafeShellCommandConstruction/UnsafeShellCommandConstruction.qlref
index fdc01b9ecbf..6d6ee0abf7d 100644
--- a/python/ql/test/query-tests/Security/CWE-078-UnsafeShellCommandConstruction/UnsafeShellCommandConstruction.qlref
+++ b/python/ql/test/query-tests/Security/CWE-078-UnsafeShellCommandConstruction/UnsafeShellCommandConstruction.qlref
@@ -1 +1 @@
-Security/CWE-078/UnsafeShellCommandConstruction.ql
+query: Security/CWE-078/UnsafeShellCommandConstruction.ql
diff --git a/python/ql/test/query-tests/Security/CWE-079-Jinja2WithoutEscaping/Jinja2WithoutEscaping.qlref b/python/ql/test/query-tests/Security/CWE-079-Jinja2WithoutEscaping/Jinja2WithoutEscaping.qlref
index 9fefcf4a030..d63a6068dc2 100644
--- a/python/ql/test/query-tests/Security/CWE-079-Jinja2WithoutEscaping/Jinja2WithoutEscaping.qlref
+++ b/python/ql/test/query-tests/Security/CWE-079-Jinja2WithoutEscaping/Jinja2WithoutEscaping.qlref
@@ -1 +1,2 @@
-Security/CWE-079/Jinja2WithoutEscaping.ql
+query: Security/CWE-079/Jinja2WithoutEscaping.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Security/CWE-079-Jinja2WithoutEscaping/jinja2_escaping.py b/python/ql/test/query-tests/Security/CWE-079-Jinja2WithoutEscaping/jinja2_escaping.py
index aed840ce886..4c63f5b5fd6 100644
--- a/python/ql/test/query-tests/Security/CWE-079-Jinja2WithoutEscaping/jinja2_escaping.py
+++ b/python/ql/test/query-tests/Security/CWE-079-Jinja2WithoutEscaping/jinja2_escaping.py
@@ -6,7 +6,7 @@ from jinja2 import Environment, select_autoescape, FileSystemLoader, Template
app = Flask(__name__)
loader = FileSystemLoader( searchpath="templates/" )
-unsafe_env = Environment(loader=loader)
+unsafe_env = Environment(loader=loader) # $ Alert
safe1_env = Environment(loader=loader, autoescape=True)
safe2_env = Environment(loader=loader, autoescape=select_autoescape())
@@ -38,18 +38,18 @@ e = Environment(
auto = select_autoescape
e = Environment(autoescape=auto) # GOOD
z = 0
-e = Environment(autoescape=z) # BAD
+e = Environment(autoescape=z) # BAD # $ Alert
E = Environment
-E() # BAD
-E(autoescape=z) # BAD
+E() # BAD # $ Alert
+E(autoescape=z) # BAD # $ Alert
E(autoescape=auto) # GOOD
E(autoescape=0+1) # GOOD
def checked(cond=False):
if cond:
- e = Environment(autoescape=cond) # GOOD
+ e = Environment(autoescape=cond) # GOOD # $ Alert
-unsafe_tmpl = Template('Hello {{ name }}!')
+unsafe_tmpl = Template('Hello {{ name }}!') # $ Alert
safe1_tmpl = Template('Hello {{ name }}!', autoescape=True)
safe2_tmpl = Template('Hello {{ name }}!', autoescape=select_autoescape())
diff --git a/python/ql/test/query-tests/Security/CWE-079-ReflectedXss/ReflectedXss.expected b/python/ql/test/query-tests/Security/CWE-079-ReflectedXss/ReflectedXss.expected
index d332231e0c9..bf4f584c815 100644
--- a/python/ql/test/query-tests/Security/CWE-079-ReflectedXss/ReflectedXss.expected
+++ b/python/ql/test/query-tests/Security/CWE-079-ReflectedXss/ReflectedXss.expected
@@ -1,3 +1,7 @@
+#select
+| reflected_xss.py:10:26:10:53 | ControlFlowNode for BinaryExpr | reflected_xss.py:2:26:2:32 | ControlFlowNode for ImportMember | reflected_xss.py:10:26:10:53 | ControlFlowNode for BinaryExpr | Cross-site scripting vulnerability due to a $@. | reflected_xss.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value |
+| reflected_xss.py:22:26:22:41 | ControlFlowNode for Attribute() | reflected_xss.py:2:26:2:32 | ControlFlowNode for ImportMember | reflected_xss.py:22:26:22:41 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to a $@. | reflected_xss.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value |
+| reflected_xss.py:28:26:28:41 | ControlFlowNode for Attribute() | reflected_xss.py:2:26:2:32 | ControlFlowNode for ImportMember | reflected_xss.py:28:26:28:41 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to a $@. | reflected_xss.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value |
edges
| reflected_xss.py:2:26:2:32 | ControlFlowNode for ImportMember | reflected_xss.py:2:26:2:32 | ControlFlowNode for request | provenance | |
| reflected_xss.py:2:26:2:32 | ControlFlowNode for request | reflected_xss.py:9:18:9:24 | ControlFlowNode for request | provenance | |
@@ -28,7 +32,3 @@ nodes
| reflected_xss.py:27:23:27:29 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| reflected_xss.py:28:26:28:41 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
subpaths
-#select
-| reflected_xss.py:10:26:10:53 | ControlFlowNode for BinaryExpr | reflected_xss.py:2:26:2:32 | ControlFlowNode for ImportMember | reflected_xss.py:10:26:10:53 | ControlFlowNode for BinaryExpr | Cross-site scripting vulnerability due to a $@. | reflected_xss.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value |
-| reflected_xss.py:22:26:22:41 | ControlFlowNode for Attribute() | reflected_xss.py:2:26:2:32 | ControlFlowNode for ImportMember | reflected_xss.py:22:26:22:41 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to a $@. | reflected_xss.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value |
-| reflected_xss.py:28:26:28:41 | ControlFlowNode for Attribute() | reflected_xss.py:2:26:2:32 | ControlFlowNode for ImportMember | reflected_xss.py:28:26:28:41 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to a $@. | reflected_xss.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value |
diff --git a/python/ql/test/query-tests/Security/CWE-079-ReflectedXss/ReflectedXss.qlref b/python/ql/test/query-tests/Security/CWE-079-ReflectedXss/ReflectedXss.qlref
index e0efe102416..9cd0122e556 100644
--- a/python/ql/test/query-tests/Security/CWE-079-ReflectedXss/ReflectedXss.qlref
+++ b/python/ql/test/query-tests/Security/CWE-079-ReflectedXss/ReflectedXss.qlref
@@ -1 +1,2 @@
-Security/CWE-079/ReflectedXss.ql
+query: Security/CWE-079/ReflectedXss.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Security/CWE-079-ReflectedXss/reflected_xss.py b/python/ql/test/query-tests/Security/CWE-079-ReflectedXss/reflected_xss.py
index 98682f04f3c..8c78cc07ba1 100644
--- a/python/ql/test/query-tests/Security/CWE-079-ReflectedXss/reflected_xss.py
+++ b/python/ql/test/query-tests/Security/CWE-079-ReflectedXss/reflected_xss.py
@@ -1,5 +1,5 @@
import json
-from flask import Flask, request, make_response, escape, jsonify
+from flask import Flask, request, make_response, escape, jsonify # $ Source
app = Flask(__name__)
@@ -7,7 +7,7 @@ app = Flask(__name__)
@app.route("/unsafe")
def unsafe():
first_name = request.args.get("name", "")
- return make_response("Your name is " + first_name) # NOT OK
+ return make_response("Your name is " + first_name) # NOT OK # $ Alert
@app.route("/safe")
@@ -19,13 +19,13 @@ def safe():
@app.route("/unsafe/json")
def unsafe_json():
data = json.loads(request.data)
- return make_response(json.dumps(data)) # NOT OK
+ return make_response(json.dumps(data)) # NOT OK # $ Alert
@app.route("/safe/json")
def safe_json():
data = json.loads(request.data)
- return make_response(json.dumps(data), 200, {'Content-Type': 'application/json'}) # OK, FP
+ return make_response(json.dumps(data), 200, {'Content-Type': 'application/json'}) # OK, FP # $ Alert
@app.route("/jsonify")
diff --git a/python/ql/test/query-tests/Security/CWE-089-SqlInjection/SqlInjection.expected b/python/ql/test/query-tests/Security/CWE-089-SqlInjection/SqlInjection.expected
index 9ff8b1d718c..c1958c23858 100644
--- a/python/ql/test/query-tests/Security/CWE-089-SqlInjection/SqlInjection.expected
+++ b/python/ql/test/query-tests/Security/CWE-089-SqlInjection/SqlInjection.expected
@@ -1,3 +1,20 @@
+#select
+| sql_injection.py:21:24:21:77 | ControlFlowNode for BinaryExpr | sql_injection.py:14:15:14:22 | ControlFlowNode for username | sql_injection.py:21:24:21:77 | ControlFlowNode for BinaryExpr | This SQL query depends on a $@. | sql_injection.py:14:15:14:22 | ControlFlowNode for username | user-provided value |
+| sql_injection.py:24:38:24:95 | ControlFlowNode for BinaryExpr | sql_injection.py:14:15:14:22 | ControlFlowNode for username | sql_injection.py:24:38:24:95 | ControlFlowNode for BinaryExpr | This SQL query depends on a $@. | sql_injection.py:14:15:14:22 | ControlFlowNode for username | user-provided value |
+| sql_injection.py:25:26:25:83 | ControlFlowNode for BinaryExpr | sql_injection.py:14:15:14:22 | ControlFlowNode for username | sql_injection.py:25:26:25:83 | ControlFlowNode for BinaryExpr | This SQL query depends on a $@. | sql_injection.py:14:15:14:22 | ControlFlowNode for username | user-provided value |
+| sql_injection.py:26:28:26:85 | ControlFlowNode for BinaryExpr | sql_injection.py:14:15:14:22 | ControlFlowNode for username | sql_injection.py:26:28:26:85 | ControlFlowNode for BinaryExpr | This SQL query depends on a $@. | sql_injection.py:14:15:14:22 | ControlFlowNode for username | user-provided value |
+| sqlalchemy_textclause.py:27:28:27:87 | ControlFlowNode for Attribute() | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:27:28:27:87 | ControlFlowNode for Attribute() | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value |
+| sqlalchemy_textclause.py:31:50:31:72 | ControlFlowNode for Attribute() | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:31:50:31:72 | ControlFlowNode for Attribute() | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value |
+| sqlalchemy_textclause.py:41:26:41:33 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:41:26:41:33 | ControlFlowNode for username | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value |
+| sqlalchemy_textclause.py:42:31:42:38 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:42:31:42:38 | ControlFlowNode for username | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value |
+| sqlalchemy_textclause.py:43:30:43:37 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:43:30:43:37 | ControlFlowNode for username | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value |
+| sqlalchemy_textclause.py:44:35:44:42 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:44:35:44:42 | ControlFlowNode for username | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value |
+| sqlalchemy_textclause.py:45:41:45:48 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:45:41:45:48 | ControlFlowNode for username | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value |
+| sqlalchemy_textclause.py:46:46:46:53 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:46:46:46:53 | ControlFlowNode for username | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value |
+| sqlalchemy_textclause.py:47:47:47:54 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:47:47:47:54 | ControlFlowNode for username | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value |
+| sqlalchemy_textclause.py:48:52:48:59 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:48:52:48:59 | ControlFlowNode for username | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value |
+| sqlalchemy_textclause.py:50:18:50:25 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:50:18:50:25 | ControlFlowNode for username | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value |
+| sqlalchemy_textclause.py:51:24:51:31 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:51:24:51:31 | ControlFlowNode for username | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value |
edges
| sql_injection.py:14:15:14:22 | ControlFlowNode for username | sql_injection.py:21:24:21:77 | ControlFlowNode for BinaryExpr | provenance | |
| sql_injection.py:14:15:14:22 | ControlFlowNode for username | sql_injection.py:24:38:24:95 | ControlFlowNode for BinaryExpr | provenance | |
@@ -35,20 +52,3 @@ nodes
| sqlalchemy_textclause.py:50:18:50:25 | ControlFlowNode for username | semmle.label | ControlFlowNode for username |
| sqlalchemy_textclause.py:51:24:51:31 | ControlFlowNode for username | semmle.label | ControlFlowNode for username |
subpaths
-#select
-| sql_injection.py:21:24:21:77 | ControlFlowNode for BinaryExpr | sql_injection.py:14:15:14:22 | ControlFlowNode for username | sql_injection.py:21:24:21:77 | ControlFlowNode for BinaryExpr | This SQL query depends on a $@. | sql_injection.py:14:15:14:22 | ControlFlowNode for username | user-provided value |
-| sql_injection.py:24:38:24:95 | ControlFlowNode for BinaryExpr | sql_injection.py:14:15:14:22 | ControlFlowNode for username | sql_injection.py:24:38:24:95 | ControlFlowNode for BinaryExpr | This SQL query depends on a $@. | sql_injection.py:14:15:14:22 | ControlFlowNode for username | user-provided value |
-| sql_injection.py:25:26:25:83 | ControlFlowNode for BinaryExpr | sql_injection.py:14:15:14:22 | ControlFlowNode for username | sql_injection.py:25:26:25:83 | ControlFlowNode for BinaryExpr | This SQL query depends on a $@. | sql_injection.py:14:15:14:22 | ControlFlowNode for username | user-provided value |
-| sql_injection.py:26:28:26:85 | ControlFlowNode for BinaryExpr | sql_injection.py:14:15:14:22 | ControlFlowNode for username | sql_injection.py:26:28:26:85 | ControlFlowNode for BinaryExpr | This SQL query depends on a $@. | sql_injection.py:14:15:14:22 | ControlFlowNode for username | user-provided value |
-| sqlalchemy_textclause.py:27:28:27:87 | ControlFlowNode for Attribute() | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:27:28:27:87 | ControlFlowNode for Attribute() | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value |
-| sqlalchemy_textclause.py:31:50:31:72 | ControlFlowNode for Attribute() | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:31:50:31:72 | ControlFlowNode for Attribute() | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value |
-| sqlalchemy_textclause.py:41:26:41:33 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:41:26:41:33 | ControlFlowNode for username | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value |
-| sqlalchemy_textclause.py:42:31:42:38 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:42:31:42:38 | ControlFlowNode for username | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value |
-| sqlalchemy_textclause.py:43:30:43:37 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:43:30:43:37 | ControlFlowNode for username | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value |
-| sqlalchemy_textclause.py:44:35:44:42 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:44:35:44:42 | ControlFlowNode for username | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value |
-| sqlalchemy_textclause.py:45:41:45:48 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:45:41:45:48 | ControlFlowNode for username | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value |
-| sqlalchemy_textclause.py:46:46:46:53 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:46:46:46:53 | ControlFlowNode for username | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value |
-| sqlalchemy_textclause.py:47:47:47:54 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:47:47:47:54 | ControlFlowNode for username | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value |
-| sqlalchemy_textclause.py:48:52:48:59 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:48:52:48:59 | ControlFlowNode for username | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value |
-| sqlalchemy_textclause.py:50:18:50:25 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:50:18:50:25 | ControlFlowNode for username | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value |
-| sqlalchemy_textclause.py:51:24:51:31 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:51:24:51:31 | ControlFlowNode for username | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value |
diff --git a/python/ql/test/query-tests/Security/CWE-089-SqlInjection/SqlInjection.qlref b/python/ql/test/query-tests/Security/CWE-089-SqlInjection/SqlInjection.qlref
index d1d02cbe8d3..444c0e5f46a 100644
--- a/python/ql/test/query-tests/Security/CWE-089-SqlInjection/SqlInjection.qlref
+++ b/python/ql/test/query-tests/Security/CWE-089-SqlInjection/SqlInjection.qlref
@@ -1 +1,2 @@
-Security/CWE-089/SqlInjection.ql
+query: Security/CWE-089/SqlInjection.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Security/CWE-089-SqlInjection/sql_injection.py b/python/ql/test/query-tests/Security/CWE-089-SqlInjection/sql_injection.py
index c79bee16cb2..52aa3169616 100644
--- a/python/ql/test/query-tests/Security/CWE-089-SqlInjection/sql_injection.py
+++ b/python/ql/test/query-tests/Security/CWE-089-SqlInjection/sql_injection.py
@@ -11,19 +11,19 @@ class User(models.Model):
pass
@app.route("/users/")
-def show_user(username):
+def show_user(username): # $ Source
with connection.cursor() as cursor:
# GOOD -- Using parameters
cursor.execute("SELECT * FROM users WHERE username = %s", username)
User.objects.raw("SELECT * FROM users WHERE username = %s", (username,))
# BAD -- Using string formatting
- cursor.execute("SELECT * FROM users WHERE username = '%s'" % username)
+ cursor.execute("SELECT * FROM users WHERE username = '%s'" % username) # $ Alert
# BAD -- other ways of executing raw SQL code with string interpolation
- User.objects.annotate(RawSQL("insert into names_file ('name') values ('%s')" % username))
- User.objects.raw("insert into names_file ('name') values ('%s')" % username)
- User.objects.extra("insert into names_file ('name') values ('%s')" % username)
+ User.objects.annotate(RawSQL("insert into names_file ('name') values ('%s')" % username)) # $ Alert
+ User.objects.raw("insert into names_file ('name') values ('%s')" % username) # $ Alert
+ User.objects.extra("insert into names_file ('name') values ('%s')" % username) # $ Alert
# BAD (but currently no custom query to find this)
#
diff --git a/python/ql/test/query-tests/Security/CWE-089-SqlInjection/sqlalchemy_textclause.py b/python/ql/test/query-tests/Security/CWE-089-SqlInjection/sqlalchemy_textclause.py
index a54d64517d4..f35b1325366 100644
--- a/python/ql/test/query-tests/Security/CWE-089-SqlInjection/sqlalchemy_textclause.py
+++ b/python/ql/test/query-tests/Security/CWE-089-SqlInjection/sqlalchemy_textclause.py
@@ -20,15 +20,15 @@ class User(Base):
@app.route("/users/")
-def show_user(username):
+def show_user(username): # $ Source
session = sqlalchemy.orm.Session(engine)
# BAD, normal SQL injection
- stmt = sqlalchemy.text("SELECT * FROM users WHERE username = '{}'".format(username))
+ stmt = sqlalchemy.text("SELECT * FROM users WHERE username = '{}'".format(username)) # $ Alert
results = session.execute(stmt).fetchall()
# BAD, allows SQL injection
- username_formatted_for_sql = sqlalchemy.text("'{}'".format(username))
+ username_formatted_for_sql = sqlalchemy.text("'{}'".format(username)) # $ Alert
stmt = sqlalchemy.select(User).where(User.username == username_formatted_for_sql)
results = session.execute(stmt).scalars().all()
@@ -38,14 +38,14 @@ def show_user(username):
# All of these should be flagged by query
- t1 = sqlalchemy.text(username)
- t2 = sqlalchemy.text(text=username)
- t3 = sqlalchemy.sql.text(username)
- t4 = sqlalchemy.sql.text(text=username)
- t5 = sqlalchemy.sql.expression.text(username)
- t6 = sqlalchemy.sql.expression.text(text=username)
- t7 = sqlalchemy.sql.expression.TextClause(username)
- t8 = sqlalchemy.sql.expression.TextClause(text=username)
+ t1 = sqlalchemy.text(username) # $ Alert
+ t2 = sqlalchemy.text(text=username) # $ Alert
+ t3 = sqlalchemy.sql.text(username) # $ Alert
+ t4 = sqlalchemy.sql.text(text=username) # $ Alert
+ t5 = sqlalchemy.sql.expression.text(username) # $ Alert
+ t6 = sqlalchemy.sql.expression.text(text=username) # $ Alert
+ t7 = sqlalchemy.sql.expression.TextClause(username) # $ Alert
+ t8 = sqlalchemy.sql.expression.TextClause(text=username) # $ Alert
- t9 = db.text(username)
- t10 = db.text(text=username)
+ t9 = db.text(username) # $ Alert
+ t10 = db.text(text=username) # $ Alert
diff --git a/python/ql/test/query-tests/Security/CWE-090-LdapInjection/LdapInjection.expected b/python/ql/test/query-tests/Security/CWE-090-LdapInjection/LdapInjection.expected
index 20170029899..ae30a38acc3 100644
--- a/python/ql/test/query-tests/Security/CWE-090-LdapInjection/LdapInjection.expected
+++ b/python/ql/test/query-tests/Security/CWE-090-LdapInjection/LdapInjection.expected
@@ -1,3 +1,14 @@
+#select
+| ldap3_bad.py:21:17:21:18 | ControlFlowNode for dn | ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap3_bad.py:21:17:21:18 | ControlFlowNode for dn | LDAP query parameter (DN) depends on a $@. | ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value |
+| ldap3_bad.py:21:21:21:33 | ControlFlowNode for search_filter | ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap3_bad.py:21:21:21:33 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value |
+| ldap3_bad.py:38:9:38:10 | ControlFlowNode for dn | ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap3_bad.py:38:9:38:10 | ControlFlowNode for dn | LDAP query parameter (DN) depends on a $@. | ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value |
+| ldap3_bad.py:38:13:38:25 | ControlFlowNode for search_filter | ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap3_bad.py:38:13:38:25 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value |
+| ldap_bad.py:21:9:21:10 | ControlFlowNode for dn | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap_bad.py:21:9:21:10 | ControlFlowNode for dn | LDAP query parameter (DN) depends on a $@. | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value |
+| ldap_bad.py:21:33:21:45 | ControlFlowNode for search_filter | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap_bad.py:21:33:21:45 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value |
+| ldap_bad.py:37:9:37:10 | ControlFlowNode for dn | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap_bad.py:37:9:37:10 | ControlFlowNode for dn | LDAP query parameter (DN) depends on a $@. | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value |
+| ldap_bad.py:37:33:37:45 | ControlFlowNode for search_filter | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap_bad.py:37:33:37:45 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value |
+| ldap_bad.py:55:9:55:10 | ControlFlowNode for dn | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap_bad.py:55:9:55:10 | ControlFlowNode for dn | LDAP query parameter (DN) depends on a $@. | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value |
+| ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value |
edges
| ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap3_bad.py:1:19:1:25 | ControlFlowNode for request | provenance | |
| ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap3_bad.py:1:19:1:25 | ControlFlowNode for request | provenance | |
@@ -108,14 +119,3 @@ nodes
| ldap_bad.py:55:9:55:10 | ControlFlowNode for dn | semmle.label | ControlFlowNode for dn |
| ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | semmle.label | ControlFlowNode for search_filter |
subpaths
-#select
-| ldap3_bad.py:21:17:21:18 | ControlFlowNode for dn | ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap3_bad.py:21:17:21:18 | ControlFlowNode for dn | LDAP query parameter (DN) depends on a $@. | ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value |
-| ldap3_bad.py:21:21:21:33 | ControlFlowNode for search_filter | ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap3_bad.py:21:21:21:33 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value |
-| ldap3_bad.py:38:9:38:10 | ControlFlowNode for dn | ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap3_bad.py:38:9:38:10 | ControlFlowNode for dn | LDAP query parameter (DN) depends on a $@. | ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value |
-| ldap3_bad.py:38:13:38:25 | ControlFlowNode for search_filter | ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap3_bad.py:38:13:38:25 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value |
-| ldap_bad.py:21:9:21:10 | ControlFlowNode for dn | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap_bad.py:21:9:21:10 | ControlFlowNode for dn | LDAP query parameter (DN) depends on a $@. | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value |
-| ldap_bad.py:21:33:21:45 | ControlFlowNode for search_filter | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap_bad.py:21:33:21:45 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value |
-| ldap_bad.py:37:9:37:10 | ControlFlowNode for dn | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap_bad.py:37:9:37:10 | ControlFlowNode for dn | LDAP query parameter (DN) depends on a $@. | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value |
-| ldap_bad.py:37:33:37:45 | ControlFlowNode for search_filter | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap_bad.py:37:33:37:45 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value |
-| ldap_bad.py:55:9:55:10 | ControlFlowNode for dn | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap_bad.py:55:9:55:10 | ControlFlowNode for dn | LDAP query parameter (DN) depends on a $@. | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value |
-| ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value |
diff --git a/python/ql/test/query-tests/Security/CWE-090-LdapInjection/LdapInjection.qlref b/python/ql/test/query-tests/Security/CWE-090-LdapInjection/LdapInjection.qlref
index 19112f987ad..87db0e58f84 100644
--- a/python/ql/test/query-tests/Security/CWE-090-LdapInjection/LdapInjection.qlref
+++ b/python/ql/test/query-tests/Security/CWE-090-LdapInjection/LdapInjection.qlref
@@ -1 +1,2 @@
-Security/CWE-090/LdapInjection.ql
+query: Security/CWE-090/LdapInjection.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Security/CWE-090-LdapInjection/ldap3_bad.py b/python/ql/test/query-tests/Security/CWE-090-LdapInjection/ldap3_bad.py
index 2edb986fccf..a69aef9ad3d 100644
--- a/python/ql/test/query-tests/Security/CWE-090-LdapInjection/ldap3_bad.py
+++ b/python/ql/test/query-tests/Security/CWE-090-LdapInjection/ldap3_bad.py
@@ -1,4 +1,4 @@
-from flask import request, Flask
+from flask import request, Flask # $ Source
import ldap3
app = Flask(__name__)
@@ -18,7 +18,7 @@ def normal():
srv = ldap3.Server('ldap://127.0.0.1')
conn = ldap3.Connection(srv, user=dn, auto_bind=True)
- conn.search(dn, search_filter)
+ conn.search(dn, search_filter) # $ Alert
@app.route("/direct")
@@ -35,7 +35,7 @@ def direct():
srv = ldap3.Server('ldap://127.0.0.1')
conn = ldap3.Connection(srv, user=dn, auto_bind=True).search(
- dn, search_filter)
+ dn, search_filter) # $ Alert
# if __name__ == "__main__":
# app.run(debug=True)
diff --git a/python/ql/test/query-tests/Security/CWE-090-LdapInjection/ldap_bad.py b/python/ql/test/query-tests/Security/CWE-090-LdapInjection/ldap_bad.py
index 133b0baaf9c..8fd38f52f57 100644
--- a/python/ql/test/query-tests/Security/CWE-090-LdapInjection/ldap_bad.py
+++ b/python/ql/test/query-tests/Security/CWE-090-LdapInjection/ldap_bad.py
@@ -1,4 +1,4 @@
-from flask import request, Flask
+from flask import request, Flask # $ Source
import ldap
app = Flask(__name__)
@@ -18,7 +18,7 @@ def normal():
ldap_connection = ldap.initialize("ldap://127.0.0.1")
user = ldap_connection.search_s(
- dn, ldap.SCOPE_SUBTREE, search_filter)
+ dn, ldap.SCOPE_SUBTREE, search_filter) # $ Alert
@app.route("/direct")
@@ -34,7 +34,7 @@ def direct():
search_filter = "(user={})".format(unsafe_filter)
user = ldap.initialize("ldap://127.0.0.1").search_s(
- dn, ldap.SCOPE_SUBTREE, search_filter)
+ dn, ldap.SCOPE_SUBTREE, search_filter) # $ Alert
@app.route("/normal_argbyname")
@@ -52,7 +52,7 @@ def normal_argbyname():
ldap_connection = ldap.initialize("ldap://127.0.0.1")
user = ldap_connection.search_s(
- dn, ldap.SCOPE_SUBTREE, filterstr=search_filter)
+ dn, ldap.SCOPE_SUBTREE, filterstr=search_filter) # $ Alert
# if __name__ == "__main__":
diff --git a/python/ql/test/query-tests/Security/CWE-113-HeaderInjection/Tests2-with-wsgi-validator/HeaderInjection.expected b/python/ql/test/query-tests/Security/CWE-113-HeaderInjection/Tests2-with-wsgi-validator/HeaderInjection.expected
index e217064d1df..58f42bec0c8 100644
--- a/python/ql/test/query-tests/Security/CWE-113-HeaderInjection/Tests2-with-wsgi-validator/HeaderInjection.expected
+++ b/python/ql/test/query-tests/Security/CWE-113-HeaderInjection/Tests2-with-wsgi-validator/HeaderInjection.expected
@@ -1,4 +1,4 @@
+#select
edges
nodes
subpaths
-#select
diff --git a/python/ql/test/query-tests/Security/CWE-113-HeaderInjection/Tests2-with-wsgi-validator/HeaderInjection.qlref b/python/ql/test/query-tests/Security/CWE-113-HeaderInjection/Tests2-with-wsgi-validator/HeaderInjection.qlref
index 7dbe28e4b59..4379f3d416b 100644
--- a/python/ql/test/query-tests/Security/CWE-113-HeaderInjection/Tests2-with-wsgi-validator/HeaderInjection.qlref
+++ b/python/ql/test/query-tests/Security/CWE-113-HeaderInjection/Tests2-with-wsgi-validator/HeaderInjection.qlref
@@ -1 +1,2 @@
-Security/CWE-113/HeaderInjection.ql
\ No newline at end of file
+query: Security/CWE-113/HeaderInjection.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Security/CWE-116-BadTagFilter/BadTagFilter.qlref b/python/ql/test/query-tests/Security/CWE-116-BadTagFilter/BadTagFilter.qlref
index e5fc84fd48a..443c007de0c 100644
--- a/python/ql/test/query-tests/Security/CWE-116-BadTagFilter/BadTagFilter.qlref
+++ b/python/ql/test/query-tests/Security/CWE-116-BadTagFilter/BadTagFilter.qlref
@@ -1 +1,2 @@
-Security/CWE-116/BadTagFilter.ql
+query: Security/CWE-116/BadTagFilter.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/python/ql/test/query-tests/Security/CWE-116-BadTagFilter/tst.py b/python/ql/test/query-tests/Security/CWE-116-BadTagFilter/tst.py
index 2c3ec0667e3..51aa659282b 100644
--- a/python/ql/test/query-tests/Security/CWE-116-BadTagFilter/tst.py
+++ b/python/ql/test/query-tests/Security/CWE-116-BadTagFilter/tst.py
@@ -1,28 +1,28 @@
import re
filters = [
- re.compile(r""".*?<\/script>""", re.IGNORECASE), # NOT OK - doesn't match newlines or ``
- re.compile(r""".*?<\/script>""", re.IGNORECASE | re.DOTALL), # NOT OK - doesn't match ``
+ re.compile(r""".*?<\/script>""", re.IGNORECASE), # NOT OK - doesn't match newlines or `` # $ Alert
+ re.compile(r""".*?<\/script>""", re.IGNORECASE | re.DOTALL), # NOT OK - doesn't match `` # $ Alert
re.compile(r""".*?<\/script[^>]*>""", re.IGNORECASE | re.DOTALL), # OK
re.compile(r"""""", re.IGNORECASE | re.DOTALL), # OK - we don't care regexps that only match comments
re.compile(r""")|([^\/\s>]+)[\S\s]*?>"""), #// NOT OK - doesn't match comments with the right capture groups
- re.compile(r"""<(?:(?:\/([^>]+)>)|(?:!--([\S|\s]*?)-->)|(?:([^\/\s>]+)((?:\s+[\w\-:.]+(?:\s*=\s*?(?:(?:"[^"]*")|(?:'[^']*')|[^\s"'\/>]+))?)*)[\S\s]*?(\/?)>))"""), # NOT OK - capture groups
- re.compile(r"""(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|)""", re.IGNORECASE), # NOT OK - capture groups
- re.compile(r"""<(?:(?:!--([\w\W]*?)-->)|(?:!\[CDATA\[([\w\W]*?)\]\]>)|(?:!DOCTYPE([\w\W]*?)>)|(?:\?([^\s\/<>]+) ?([\w\W]*?)[?/]>)|(?:\/([A-Za-z][A-Za-z0-9\-_\:\.]*)>)|(?:([A-Za-z][A-Za-z0-9\-_\:\.]*)((?:\s+[^"'>]+(?:(?:"[^"]*")|(?:'[^']*')|[^>]*))*|\/|\s+)>))"""), # NOT OK - capture groups
+ re.compile(r"""