Merge branch 'main' into typetracker-decorators

This commit is contained in:
Rasmus Wriedt Larsen
2022-08-08 11:52:09 +02:00
committed by GitHub
2041 changed files with 142769 additions and 119477 deletions

View File

@@ -37,6 +37,10 @@ f = not_found.get_passwd # $ SensitiveDataSource=password
x = f()
print(x) # $ SensitiveUse=password
# some prefixes makes us ignore it as a source
not_found.isSecret
not_found.is_secret
def my_func(non_sensitive_name):
x = non_sensitive_name()
print(x) # $ SensitiveUse=password
@@ -56,6 +60,11 @@ getattr(foo, x) # $ SensitiveDataSource=password
def my_func(password): # $ SensitiveDataSource=password
print(password) # $ SensitiveUse=password
# FP where the `cert` in `uncertainty` makes us treat it like a certificate
# https://github.com/github/codeql/issues/9632
def my_other_func(uncertainty):
print(uncertainty)
password = some_function() # $ SensitiveDataSource=password
print(password) # $ SensitiveUse=password

View File

@@ -2,7 +2,5 @@ import experimental.meta.InlineTaintTest
import semmle.python.dataflow.new.BarrierGuards
class CustomSanitizerOverrides extends TestTaintTrackingConfiguration {
override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) {
guard instanceof StringConstCompare
}
override predicate isSanitizer(DataFlow::Node node) { node instanceof StringConstCompareBarrier }
}

View File

@@ -50,7 +50,7 @@ def test_non_eq2():
if not ts == "safe":
ensure_tainted(ts) # $ tainted
else:
ensure_not_tainted(ts) # $ SPURIOUS: tainted
ensure_not_tainted(ts)
def test_in_list():
@@ -157,7 +157,7 @@ def test_not_in2():
if not ts in ["safe", "also_safe"]:
ensure_tainted(ts) # $ tainted
else:
ensure_not_tainted(ts) # $ SPURIOUS: tainted
ensure_not_tainted(ts)
def is_safe(x):

View File

@@ -4,20 +4,22 @@ failures
isSanitizer
| TestTaintTrackingConfiguration | test.py:21:39:21:39 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test.py:34:39:34:39 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test.py:52:28:52:28 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test.py:66:10:66:29 | ControlFlowNode for emulated_escaping() |
isSanitizerGuard
| TestTaintTrackingConfiguration | test.py:51:8:51:26 | ControlFlowNode for emulated_is_safe() |
| TestTaintTrackingConfiguration | test_logical.py:29:8:29:17 | ControlFlowNode for is_safe() |
| TestTaintTrackingConfiguration | test_logical.py:44:8:44:17 | ControlFlowNode for is_safe() |
| TestTaintTrackingConfiguration | test_logical.py:49:8:49:17 | ControlFlowNode for is_safe() |
| TestTaintTrackingConfiguration | test_logical.py:59:8:59:17 | ControlFlowNode for is_safe() |
| TestTaintTrackingConfiguration | test_logical.py:67:12:67:21 | ControlFlowNode for is_safe() |
| TestTaintTrackingConfiguration | test_logical.py:87:8:87:17 | ControlFlowNode for is_safe() |
| TestTaintTrackingConfiguration | test_logical.py:95:12:95:21 | ControlFlowNode for is_safe() |
| TestTaintTrackingConfiguration | test_logical.py:119:8:119:17 | ControlFlowNode for is_safe() |
| TestTaintTrackingConfiguration | test_logical.py:142:12:142:21 | ControlFlowNode for is_safe() |
| TestTaintTrackingConfiguration | test_logical.py:147:16:147:25 | ControlFlowNode for is_safe() |
| TestTaintTrackingConfiguration | test_logical.py:152:20:152:29 | ControlFlowNode for is_safe() |
| TestTaintTrackingConfiguration | test_reference.py:30:8:30:17 | ControlFlowNode for is_safe() |
| TestTaintTrackingConfiguration | test_reference.py:40:8:40:25 | ControlFlowNode for is_safe() |
| TestTaintTrackingConfiguration | test_reference.py:55:8:55:21 | ControlFlowNode for is_safe() |
| TestTaintTrackingConfiguration | test_logical.py:33:28:33:28 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test_logical.py:40:28:40:28 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test_logical.py:48:28:48:28 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test_logical.py:53:28:53:28 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test_logical.py:92:28:92:28 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test_logical.py:103:28:103:28 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test_logical.py:111:28:111:28 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test_logical.py:130:28:130:28 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test_logical.py:137:28:137:28 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test_logical.py:148:28:148:28 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test_logical.py:151:28:151:28 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test_logical.py:158:28:158:28 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test_logical.py:167:24:167:24 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test_logical.py:176:24:176:24 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test_logical.py:185:24:185:24 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test_logical.py:193:24:193:24 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test_reference.py:31:28:31:28 | ControlFlowNode for s |

View File

@@ -1,14 +1,15 @@
import experimental.meta.InlineTaintTest
class IsSafeCheck extends DataFlow::BarrierGuard {
IsSafeCheck() {
this.(CallNode).getNode().getFunc().(Name).getId() in ["is_safe", "emulated_is_safe"]
}
predicate isSafeCheck(DataFlow::GuardNode g, ControlFlowNode node, boolean branch) {
g.(CallNode).getNode().getFunc().(Name).getId() in ["is_safe", "emulated_is_safe"] and
node = g.(CallNode).getAnArg() and
branch = true
}
override predicate checks(ControlFlowNode node, boolean branch) {
node = this.(CallNode).getAnArg() and
branch = true
}
predicate isUnsafeCheck(DataFlow::GuardNode g, ControlFlowNode node, boolean branch) {
g.(CallNode).getNode().getFunc().(Name).getId() in ["is_unsafe", "emulated_is_unsafe"] and
node = g.(CallNode).getAnArg() and
branch = false
}
class CustomSanitizerOverrides extends TestTaintTrackingConfiguration {
@@ -19,17 +20,14 @@ class CustomSanitizerOverrides extends TestTaintTrackingConfiguration {
)
or
node.asExpr().(Call).getFunc().(Name).getId() = "emulated_escaping"
or
node = DataFlow::BarrierGuard<isSafeCheck/3>::getABarrierNode()
or
node = DataFlow::BarrierGuard<isUnsafeCheck/3>::getABarrierNode()
}
override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { guard instanceof IsSafeCheck }
}
query predicate isSanitizer(TestTaintTrackingConfiguration conf, DataFlow::Node node) {
exists(node.getLocation().getFile().getRelativePath()) and
conf.isSanitizer(node)
}
query predicate isSanitizerGuard(TestTaintTrackingConfiguration conf, DataFlow::BarrierGuard guard) {
exists(guard.getLocation().getFile().getRelativePath()) and
conf.isSanitizerGuard(guard)
}

View File

@@ -22,6 +22,9 @@ def random_choice():
def is_safe(arg):
return arg == "safe"
def is_unsafe(arg):
return arg == TAINTED_STRING
def test_basic():
s = TAINTED_STRING
@@ -34,7 +37,7 @@ def test_basic():
if not is_safe(s):
ensure_tainted(s) # $ tainted
else:
ensure_not_tainted(s) # $ SPURIOUS: tainted
ensure_not_tainted(s)
def test_if_in_depth():
@@ -105,7 +108,7 @@ def test_and():
ensure_tainted(s) # $ tainted
else:
# cannot be tainted
ensure_not_tainted(s) # $ SPURIOUS: tainted
ensure_not_tainted(s)
def test_tricky():
@@ -124,14 +127,14 @@ def test_nesting_not():
s = TAINTED_STRING
if not(not(is_safe(s))):
ensure_not_tainted(s) # $ SPURIOUS: tainted
ensure_not_tainted(s)
else:
ensure_tainted(s) # $ tainted
if not(not(not(is_safe(s)))):
ensure_tainted(s) # $ tainted
else:
ensure_not_tainted(s) # $ SPURIOUS: tainted
ensure_not_tainted(s)
# Adding `and True` makes the sanitizer trigger when it would otherwise not. See output in
@@ -161,7 +164,16 @@ def test_with_return():
if not is_safe(s):
return
ensure_not_tainted(s) # $ SPURIOUS: tainted
ensure_not_tainted(s)
def test_with_return_neg():
s = TAINTED_STRING
if is_unsafe(s):
return
ensure_not_tainted(s)
def test_with_exception():
@@ -170,7 +182,15 @@ def test_with_exception():
if not is_safe(s):
raise Exception("unsafe")
ensure_not_tainted(s) # $ SPURIOUS: tainted
ensure_not_tainted(s)
def test_with_exception_neg():
s = TAINTED_STRING
if is_unsafe(s):
raise Exception("unsafe")
ensure_not_tainted(s)
# Make tests runable
@@ -182,7 +202,12 @@ test_tricky()
test_nesting_not()
test_nesting_not_with_and_true()
test_with_return()
test_with_return_neg()
try:
test_with_exception()
except:
pass
try:
test_with_exception_neg()
except:
pass

View File

@@ -5,7 +5,7 @@ import semmle.python.ApiGraphs
private DataFlow::TypeTrackingNode module_tracker(TypeTracker t) {
t.start() and
result = API::moduleImport("module").getAnImmediateUse()
result = API::moduleImport("module").asSource()
or
exists(TypeTracker t2 | result = module_tracker(t2).track(t2, t))
}

View File

@@ -120,7 +120,7 @@ class TrackedSelfTest extends InlineExpectationsTest {
/** Gets a reference to `foo` (fictive module). */
private DataFlow::TypeTrackingNode foo(DataFlow::TypeTracker t) {
t.start() and
result = API::moduleImport("foo").getAnImmediateUse()
result = API::moduleImport("foo").asSource()
or
exists(DataFlow::TypeTracker t2 | result = foo(t2).track(t2, t))
}
@@ -131,7 +131,7 @@ DataFlow::Node foo() { foo(DataFlow::TypeTracker::end()).flowsTo(result) }
/** Gets a reference to `foo.bar` (fictive module). */
private DataFlow::TypeTrackingNode foo_bar(DataFlow::TypeTracker t) {
t.start() and
result = API::moduleImport("foo").getMember("bar").getAnImmediateUse()
result = API::moduleImport("foo").getMember("bar").asSource()
or
t.startInAttr("bar") and
result = foo()
@@ -145,7 +145,7 @@ DataFlow::Node foo_bar() { foo_bar(DataFlow::TypeTracker::end()).flowsTo(result)
/** Gets a reference to `foo.bar.baz` (fictive attribute on `foo.bar` module). */
private DataFlow::TypeTrackingNode foo_bar_baz(DataFlow::TypeTracker t) {
t.start() and
result = API::moduleImport("foo").getMember("bar").getMember("baz").getAnImmediateUse()
result = API::moduleImport("foo").getMember("bar").getMember("baz").asSource()
or
t.startInAttr("baz") and
result = foo_bar()