mirror of
https://github.com/github/codeql.git
synced 2026-05-04 13:15:21 +02:00
Merge branch 'main' into typetracker-decorators
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user