@@ -92,27 +92,33 @@ module CleartextLogging {
9292 }
9393
9494 /**
95- * Gets the name of a method that would be falsely marked as non-sensitive
96- * by `notSensitiveRegexp` .
95+ * Holds if ` name` is for a method or variable that appears, syntactically, to
96+ * not be sensitive .
9797 */
98- private predicate nonSensitiveMethodNameExclusion ( string name ) { name = [ "[]" , "[]=" ] }
98+ bindingset [ name]
99+ private predicate nameIsNotSensitive ( string name ) {
100+ name .regexpMatch ( notSensitiveRegexp ( ) ) and
101+ // By default `notSensitiveRegexp()` includes some false positives for
102+ // common ruby method names that are not necessarily non-sensitive.
103+ // We explicitly exclude element references, element assignments, and
104+ // mutation methods.
105+ not name = [ "[]" , "[]=" ] and
106+ not name .suffix ( 1 ) = "!"
107+ }
99108
100109 /**
101110 * A call that might obfuscate a password, for example through hashing.
102111 */
103112 private class ObfuscatorCall extends Sanitizer , DataFlow:: CallNode {
104- ObfuscatorCall ( ) {
105- this .getMethodName ( ) .regexpMatch ( notSensitiveRegexp ( ) ) and
106- not nonSensitiveMethodNameExclusion ( this .getMethodName ( ) )
107- }
113+ ObfuscatorCall ( ) { nameIsNotSensitive ( this .getMethodName ( ) ) }
108114 }
109115
110116 /**
111117 * A data flow node that does not contain a clear-text password, according to its syntactic name.
112118 */
113119 private class NameGuidedNonCleartextPassword extends NonCleartextPassword {
114120 NameGuidedNonCleartextPassword ( ) {
115- exists ( string name | name . regexpMatch ( notSensitiveRegexp ( ) ) |
121+ exists ( string name | nameIsNotSensitive ( name ) |
116122 // accessing a non-sensitive variable
117123 this .asExpr ( ) .getExpr ( ) .( VariableReadAccess ) .getVariable ( ) .getName ( ) = name
118124 or
@@ -125,8 +131,7 @@ module CleartextLogging {
125131 .getStringOrSymbol ( ) = name
126132 or
127133 // calling a non-sensitive method
128- this .( DataFlow:: CallNode ) .getMethodName ( ) = name and
129- not nonSensitiveMethodNameExclusion ( name )
134+ this .( DataFlow:: CallNode ) .getMethodName ( ) = name
130135 )
131136 or
132137 // avoid i18n strings
@@ -175,7 +180,7 @@ module CleartextLogging {
175180 HashKeyWritePasswordSource ( ) {
176181 exists ( DataFlow:: Node val |
177182 name .regexpMatch ( maybePassword ( ) ) and
178- not name . regexpMatch ( notSensitiveRegexp ( ) ) and
183+ not nameIsNotSensitive ( name ) and
179184 // avoid safe values assigned to presumably unsafe names
180185 not val instanceof NonCleartextPassword and
181186 (
0 commit comments