mirror of
https://github.com/github/codeql.git
synced 2026-04-26 09:15:12 +02:00
Python: Fix problems with sinks in pathlib
This must mean that we did not have this flow with the old call-graph, which means the new call-graph is doing a better job (yay).
This commit is contained in:
@@ -50,7 +50,34 @@ module CleartextStorage {
|
||||
|
||||
/** The data written to a file, considered as a flow sink. */
|
||||
class FileWriteDataAsSink extends Sink {
|
||||
FileWriteDataAsSink() { this = any(FileSystemWriteAccess write).getADataNode() }
|
||||
FileWriteDataAsSink() {
|
||||
this = any(FileSystemWriteAccess write).getADataNode() and
|
||||
// since implementation of Path.write_bytes in pathlib.py is like
|
||||
// ```py
|
||||
// def write_bytes(self, data):
|
||||
// with self.open(mode='wb') as f:
|
||||
// return f.write(data)
|
||||
// ```
|
||||
// any time we would report flow to the `Path.write_bytes` sink, we can ALSO report
|
||||
// the flow from the `data` parameter to the `f.write` sink -- obviously we
|
||||
// don't want that.
|
||||
//
|
||||
// However, simply removing taint edges out of a sink is not a good enough solution,
|
||||
// since we would only flag one of the `p.write` calls in the following example
|
||||
// due to use-use flow
|
||||
// ```py
|
||||
// p.write(user_controlled)
|
||||
// p.write(user_controlled)
|
||||
// ```
|
||||
//
|
||||
// The same approach is used in the command injection query.
|
||||
not exists(Module pathlib |
|
||||
pathlib.getName() = "pathlib" and
|
||||
this.getScope().getEnclosingModule() = pathlib and
|
||||
// do allow this call if we're analyzing pathlib.py as part of CPython though
|
||||
not exists(pathlib.getFile().getRelativePath())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** The data written to a cookie on a HTTP response, considered as a flow sink. */
|
||||
|
||||
@@ -76,6 +76,8 @@ module CommandInjection {
|
||||
// `subprocess`. See:
|
||||
// https://github.com/python/cpython/blob/fa7ce080175f65d678a7d5756c94f82887fc9803/Lib/os.py#L974
|
||||
// https://github.com/python/cpython/blob/fa7ce080175f65d678a7d5756c94f82887fc9803/Lib/subprocess.py#L341
|
||||
//
|
||||
// The same approach is used in the path-injection and cleartext-storage queries.
|
||||
not this.getScope().getEnclosingModule().getName() in [
|
||||
"os", "subprocess", "platform", "popen2"
|
||||
]
|
||||
|
||||
@@ -58,7 +58,33 @@ module PathInjection {
|
||||
* A file system access, considered as a flow sink.
|
||||
*/
|
||||
class FileSystemAccessAsSink extends Sink {
|
||||
FileSystemAccessAsSink() { this = any(FileSystemAccess e).getAPathArgument() }
|
||||
FileSystemAccessAsSink() {
|
||||
this = any(FileSystemAccess e).getAPathArgument() and
|
||||
// since implementation of Path.open in pathlib.py is like
|
||||
// ```py
|
||||
// def open(self, ...):
|
||||
// return io.open(self, ...)
|
||||
// ```
|
||||
// any time we would report flow to the `path_obj.open` sink, we can ALSO report
|
||||
// the flow from the `self` parameter to the `io.open` sink -- obviously we
|
||||
// don't want that.
|
||||
//
|
||||
// However, simply removing taint edges out of a sink is not a good enough solution,
|
||||
// since we would only flag one of the `p.open` calls in the following example
|
||||
// due to use-use flow
|
||||
// ```py
|
||||
// p.open()
|
||||
// p.open()
|
||||
// ```
|
||||
//
|
||||
// The same approach is used in the command injection query.
|
||||
not exists(Module pathlib |
|
||||
pathlib.getName() = "pathlib" and
|
||||
this.getScope().getEnclosingModule() = pathlib and
|
||||
// do allow this call if we're analyzing pathlib.py as part of CPython though
|
||||
not exists(pathlib.getFile().getRelativePath())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private import semmle.python.frameworks.data.ModelsAsData
|
||||
|
||||
Reference in New Issue
Block a user