mirror of
https://github.com/github/codeql.git
synced 2025-12-24 04:36:35 +01:00
Python: Add additional taint steps for containers
This commit is contained in:
@@ -32,6 +32,8 @@ predicate localAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeT
|
||||
stringManipulation(nodeFrom, nodeTo)
|
||||
or
|
||||
jsonStep(nodeFrom, nodeTo)
|
||||
or
|
||||
containerStep(nodeFrom, nodeTo)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,3 +137,38 @@ predicate jsonStep(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeTo) {
|
||||
call.getArg(0) = nodeFrom.getNode()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if taint can flow from `nodeFrom` to `nodeTo` with a step related to containers
|
||||
* (lists/sets/dictionaries): literals, constructor invocation, methods. Note that this
|
||||
* is currently very imprecise, as an example, since we model `dict.get`, we treat any
|
||||
* `<tainted object>.get(<arg>)` will be tainted, whether it's true or not.
|
||||
*/
|
||||
predicate containerStep(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeTo) {
|
||||
// construction by literal
|
||||
// TODO: Not limiting the content argument here feels like a BIG hack, but we currently get nothing for free :|
|
||||
storeStep(nodeFrom, _, nodeTo)
|
||||
or
|
||||
// constructor call
|
||||
exists(CallNode call | call = nodeTo.getNode() |
|
||||
call.getFunction().(NameNode).getId() in ["list", "set", "frozenset", "dict", "defaultdict", "tuple"] and
|
||||
call.getArg(0) = nodeFrom.getNode()
|
||||
)
|
||||
or
|
||||
// functions operating on collections
|
||||
exists(CallNode call | call = nodeTo.getNode() |
|
||||
call.getFunction().(NameNode).getId() in ["sorted", "reversed", "iter", "next"] and
|
||||
call.getArg(0) = nodeFrom.getNode()
|
||||
)
|
||||
or
|
||||
// methods
|
||||
exists(CallNode call, string name | call = nodeTo.getNode() |
|
||||
name in [
|
||||
// general
|
||||
"copy", "pop",
|
||||
// dict
|
||||
"values", "items", "get", "popitem"
|
||||
] and
|
||||
call.getFunction().(AttrNode).getObject(name) = nodeFrom.getNode()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
| collections.py:16 | fail | test_access | tainted_list.copy() |
|
||||
| collections.py:16 | ok | test_access | tainted_list.copy() |
|
||||
| string.py:17 | ok | str_methods | ts.casefold() |
|
||||
| string.py:19 | ok | str_methods | ts.format_map(..) |
|
||||
| string.py:20 | fail | str_methods | "{unsafe}".format_map(..) |
|
||||
| string.py:20 | ok | str_methods | "{unsafe}".format_map(..) |
|
||||
| string.py:31 | fail | binary_decode_encode | base64.a85encode(..) |
|
||||
| string.py:32 | fail | binary_decode_encode | base64.a85decode(..) |
|
||||
| string.py:35 | fail | binary_decode_encode | base64.b85encode(..) |
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
| collections.py:24 | ok | test_construction | tainted_string |
|
||||
| collections.py:25 | fail | test_construction | tainted_list |
|
||||
| collections.py:26 | fail | test_construction | tainted_tuple |
|
||||
| collections.py:27 | fail | test_construction | tainted_set |
|
||||
| collections.py:28 | fail | test_construction | tainted_dict |
|
||||
| collections.py:32 | fail | test_construction | list(..) |
|
||||
| collections.py:33 | fail | test_construction | list(..) |
|
||||
| collections.py:34 | fail | test_construction | list(..) |
|
||||
| collections.py:35 | fail | test_construction | list(..) |
|
||||
| collections.py:36 | fail | test_construction | list(..) |
|
||||
| collections.py:38 | fail | test_construction | tuple(..) |
|
||||
| collections.py:39 | fail | test_construction | set(..) |
|
||||
| collections.py:40 | fail | test_construction | frozenset(..) |
|
||||
| collections.py:25 | ok | test_construction | tainted_list |
|
||||
| collections.py:26 | ok | test_construction | tainted_tuple |
|
||||
| collections.py:27 | ok | test_construction | tainted_set |
|
||||
| collections.py:28 | ok | test_construction | tainted_dict |
|
||||
| collections.py:32 | ok | test_construction | list(..) |
|
||||
| collections.py:33 | ok | test_construction | list(..) |
|
||||
| collections.py:34 | ok | test_construction | list(..) |
|
||||
| collections.py:35 | ok | test_construction | list(..) |
|
||||
| collections.py:36 | ok | test_construction | list(..) |
|
||||
| collections.py:38 | ok | test_construction | tuple(..) |
|
||||
| collections.py:39 | ok | test_construction | set(..) |
|
||||
| collections.py:40 | ok | test_construction | frozenset(..) |
|
||||
| collections.py:48 | ok | test_access | tainted_list[0] |
|
||||
| collections.py:49 | ok | test_access | tainted_list[x] |
|
||||
| collections.py:50 | ok | test_access | tainted_list[Slice] |
|
||||
| collections.py:52 | fail | test_access | sorted(..) |
|
||||
| collections.py:53 | fail | test_access | reversed(..) |
|
||||
| collections.py:54 | fail | test_access | iter(..) |
|
||||
| collections.py:55 | fail | test_access | next(..) |
|
||||
| collections.py:52 | ok | test_access | sorted(..) |
|
||||
| collections.py:53 | ok | test_access | reversed(..) |
|
||||
| collections.py:54 | ok | test_access | iter(..) |
|
||||
| collections.py:55 | ok | test_access | next(..) |
|
||||
| collections.py:56 | fail | test_access | copy(..) |
|
||||
| collections.py:57 | ok | test_access | deepcopy(..) |
|
||||
| collections.py:61 | fail | test_access | a |
|
||||
@@ -26,9 +26,9 @@
|
||||
| collections.py:64 | fail | test_access | h |
|
||||
| collections.py:66 | fail | test_access | i |
|
||||
| collections.py:73 | ok | test_dict_access | tainted_dict["name"] |
|
||||
| collections.py:74 | fail | test_dict_access | tainted_dict.get(..) |
|
||||
| collections.py:74 | ok | test_dict_access | tainted_dict.get(..) |
|
||||
| collections.py:75 | ok | test_dict_access | tainted_dict[x] |
|
||||
| collections.py:76 | fail | test_dict_access | tainted_dict.copy() |
|
||||
| collections.py:76 | ok | test_dict_access | tainted_dict.copy() |
|
||||
| collections.py:80 | fail | test_dict_access | v |
|
||||
| collections.py:82 | fail | test_dict_access | v |
|
||||
| collections.py:90 | fail | test_named_tuple | point[0] |
|
||||
@@ -70,7 +70,7 @@
|
||||
| string.py:49 | ok | str_methods | "{}".format(..) |
|
||||
| string.py:50 | ok | str_methods | "{unsafe}".format(..) |
|
||||
| string.py:52 | ok | str_methods | ts.join(..) |
|
||||
| string.py:53 | fail | str_methods | "".join(..) |
|
||||
| string.py:53 | ok | str_methods | "".join(..) |
|
||||
| string.py:55 | ok | str_methods | ts.ljust(..) |
|
||||
| string.py:56 | ok | str_methods | ts.lstrip() |
|
||||
| string.py:57 | ok | str_methods | ts.lower() |
|
||||
@@ -99,7 +99,7 @@
|
||||
| string.py:100 | fail | non_syntactic | _str(..) |
|
||||
| string.py:109 | ok | percent_fmt | BinaryExpr |
|
||||
| string.py:110 | ok | percent_fmt | BinaryExpr |
|
||||
| string.py:111 | fail | percent_fmt | BinaryExpr |
|
||||
| string.py:111 | ok | percent_fmt | BinaryExpr |
|
||||
| string.py:121 | fail | binary_decode_encode | base64.b64encode(..) |
|
||||
| string.py:122 | fail | binary_decode_encode | base64.b64decode(..) |
|
||||
| string.py:124 | fail | binary_decode_encode | base64.standard_b64encode(..) |
|
||||
|
||||
Reference in New Issue
Block a user