Skip to content

Commit e04d1ff

Browse files
committed
Python: Add test for fabric.api.execute
1 parent 7716cff commit e04d1ff

File tree

6 files changed

+88
-0
lines changed

6 files changed

+88
-0
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import python
2+
import semmle.python.dataflow.TaintTracking
3+
import semmle.python.security.strings.Untrusted
4+
5+
class SimpleSource extends TaintSource {
6+
SimpleSource() { this.(NameNode).getId() = "TAINTED_STRING" }
7+
8+
override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringKind }
9+
10+
override string toString() { result = "taint source" }
11+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
| test.py:8 | fail | unsafe | cmd | <NO TAINT> |
2+
| test.py:8 | fail | unsafe | cmd2 | <NO TAINT> |
3+
| test.py:9 | ok | unsafe | safe_arg | <NO TAINT> |
4+
| test.py:9 | ok | unsafe | safe_optional | <NO TAINT> |
5+
| test.py:16 | fail | unsafe | cmd | <NO TAINT> |
6+
| test.py:16 | fail | unsafe | cmd2 | <NO TAINT> |
7+
| test.py:17 | ok | unsafe | safe_arg | <NO TAINT> |
8+
| test.py:17 | ok | unsafe | safe_optional | <NO TAINT> |
9+
| test.py:23 | ok | some_http_handler | cmd | externally controlled string |
10+
| test.py:23 | ok | some_http_handler | cmd2 | externally controlled string |
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import python
2+
import semmle.python.security.TaintTracking
3+
import semmle.python.web.HttpRequest
4+
import semmle.python.security.strings.Untrusted
5+
6+
import Taint
7+
8+
from
9+
Call call, Expr arg, boolean expected_taint, boolean has_taint, string test_res,
10+
string taint_string
11+
where
12+
call.getLocation().getFile().getShortName() = "test.py" and
13+
(
14+
call.getFunc().(Name).getId() = "ensure_tainted" and
15+
expected_taint = true
16+
or
17+
call.getFunc().(Name).getId() = "ensure_not_tainted" and
18+
expected_taint = false
19+
) and
20+
arg = call.getAnArg() and
21+
(
22+
not exists(TaintedNode tainted | tainted.getAstNode() = arg) and
23+
taint_string = "<NO TAINT>" and
24+
has_taint = false
25+
or
26+
exists(TaintedNode tainted | tainted.getAstNode() = arg |
27+
taint_string = tainted.getTaintKind().toString()
28+
) and
29+
has_taint = true
30+
) and
31+
if expected_taint = has_taint then test_res = "ok " else test_res = "fail"
32+
// if expected_taint = has_taint then test_res = "✓" else test_res = "✕"
33+
select arg.getLocation().toString(), test_res, call.getScope().(Function).getName(), arg.toString(),
34+
taint_string
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
semmle-extractor-options: --max-import-depth=2 -p ../../../query-tests/Security/lib/
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
"""Test that shows fabric.api.execute propagates taint"""
2+
3+
from fabric.api import run, execute
4+
5+
6+
def unsafe(cmd, safe_arg, cmd2=None, safe_optional=5):
7+
run('./venv/bin/activate && {}'.format(cmd))
8+
ensure_tainted(cmd, cmd2)
9+
ensure_not_tainted(safe_arg, safe_optional)
10+
11+
12+
class Foo(object):
13+
14+
def unsafe(self, cmd, safe_arg, cmd2=None, safe_optional=5):
15+
run('./venv/bin/activate && {}'.format(cmd))
16+
ensure_tainted(cmd, cmd2)
17+
ensure_not_tainted(safe_arg, safe_optional)
18+
19+
20+
def some_http_handler():
21+
cmd = TAINTED_STRING
22+
cmd2 = TAINTED_STRING
23+
ensure_tainted(cmd, cmd2)
24+
25+
execute(unsafe, cmd=cmd, safe_arg='safe_arg', cmd2=cmd2)
26+
27+
foo = Foo()
28+
execute(foo.unsafe, cmd, 'safe_arg', cmd2)

python/ql/test/query-tests/Security/lib/fabric/api.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,7 @@ def sudo(command, shell=True, pty=True, combine_stderr=None, user=None,
2323
quiet=False, warn_only=False, stdout=None, stderr=None, group=None,
2424
timeout=None, shell_escape=None, capture_buffer_size=None):
2525
pass
26+
27+
# https://github.com/fabric/fabric/blob/1.14/fabric/tasks.py#L281
28+
def execute(task, *args, **kwargs):
29+
pass

0 commit comments

Comments
 (0)