Skip to content

Commit a301c93

Browse files
committed
Python: Fix results outside DB for CleartextLogging
1 parent 0a41d8d commit a301c93

File tree

3 files changed

+39
-108
lines changed

3 files changed

+39
-108
lines changed

python/ql/lib/semmle/python/security/dataflow/CleartextLoggingCustomizations.qll

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,16 +57,43 @@ module CleartextLogging {
5757
/** A piece of data printed, considered as a flow sink. */
5858
class PrintedDataAsSink extends Sink {
5959
PrintedDataAsSink() {
60-
this = API::builtin("print").getACall().getArg(_)
61-
or
62-
// special handling of writing to `sys.stdout` and `sys.stderr`, which is
63-
// essentially the same as printing
64-
this =
65-
API::moduleImport("sys")
66-
.getMember(["stdout", "stderr"])
67-
.getMember("write")
68-
.getACall()
69-
.getArg(0)
60+
(
61+
this = API::builtin("print").getACall().getArg(_)
62+
or
63+
// special handling of writing to `sys.stdout` and `sys.stderr`, which is
64+
// essentially the same as printing
65+
this =
66+
API::moduleImport("sys")
67+
.getMember(["stdout", "stderr"])
68+
.getMember("write")
69+
.getACall()
70+
.getArg(0)
71+
) and
72+
// since some of the inner error handling implementation of the logging module is
73+
// ```py
74+
// sys.stderr.write('Message: %r\n'
75+
// 'Arguments: %s\n' % (record.msg,
76+
// record.args))
77+
// ```
78+
// any time we would report flow to such a logging sink, we can ALSO report
79+
// the flow to the `record.msg`/`record.args` sinks -- obviously we
80+
// don't want that.
81+
//
82+
// However, simply removing taint edges out of a sink is not a good enough solution,
83+
// since we would only flag one of the `logging.info` calls in the following example
84+
// due to use-use flow
85+
// ```py
86+
// logging.info(user_controlled)
87+
// logging.info(user_controlled)
88+
// ```
89+
//
90+
// The same approach is used in the command injection query.
91+
not exists(Module loggingInit |
92+
loggingInit.getName() = "logging.__init__" and
93+
this.getScope().getEnclosingModule() = loggingInit and
94+
// do allow this call if we're analyzing logging/__init__.py as part of CPython though
95+
not exists(loggingInit.getFile().getRelativePath())
96+
)
7097
}
7198
}
7299
}

python/ql/lib/semmle/python/security/dataflow/CommandInjectionCustomizations.qll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ module CommandInjection {
7777
// https://github.com/python/cpython/blob/fa7ce080175f65d678a7d5756c94f82887fc9803/Lib/os.py#L974
7878
// https://github.com/python/cpython/blob/fa7ce080175f65d678a7d5756c94f82887fc9803/Lib/subprocess.py#L341
7979
//
80-
// The same approach is used in the path-injection and cleartext-storage queries.
80+
// The same approach is used in the path-injection, cleartext-storage, and
81+
// cleartext-logging queries.
8182
not this.getScope().getEnclosingModule().getName() in [
8283
"os", "subprocess", "platform", "popen2"
8384
]

0 commit comments

Comments
 (0)