@@ -47,7 +47,35 @@ module LogInjection {
47
47
* A logging operation, considered as a flow sink.
48
48
*/
49
49
class LoggingAsSink extends Sink {
50
- LoggingAsSink ( ) { this = any ( Logging write ) .getAnInput ( ) }
50
+ LoggingAsSink ( ) {
51
+ this = any ( Logging write ) .getAnInput ( ) and
52
+ // since the inner implementation of the `logging.Logger.warn` function is
53
+ // ```py
54
+ // class Logger:
55
+ // def warn(self, msg, *args, **kwargs):
56
+ // warnings.warn("The 'warn' method is deprecated, "
57
+ // "use 'warning' instead", DeprecationWarning, 2)
58
+ // self.warning(msg, *args, **kwargs)
59
+ // ```
60
+ // any time we would report flow to such a logging sink, we can ALSO report
61
+ // the flow to the `self.warning` sink -- obviously we don't want that.
62
+ //
63
+ // However, simply removing taint edges out of a sink is not a good enough solution,
64
+ // since we would only flag one of the `logging.info` calls in the following example
65
+ // due to use-use flow
66
+ // ```py
67
+ // logger.warn(user_controlled)
68
+ // logger.warn(user_controlled)
69
+ // ```
70
+ //
71
+ // The same approach is used in the command injection query.
72
+ not exists ( Module loggingInit |
73
+ loggingInit .getName ( ) = "logging.__init__" and
74
+ this .getScope ( ) .getEnclosingModule ( ) = loggingInit and
75
+ // do allow this call if we're analyzing logging/__init__.py as part of CPython though
76
+ not exists ( loggingInit .getFile ( ) .getRelativePath ( ) )
77
+ )
78
+ }
51
79
}
52
80
53
81
/**
0 commit comments