Skip to content

Commit 83a3808

Browse files
committed
Ruby: avoid marking mutator methods as being safe (i.e. not returning sensitive data)
1 parent b46e4cc commit 83a3808

File tree

1 file changed

+16
-11
lines changed

1 file changed

+16
-11
lines changed

ruby/ql/lib/codeql/ruby/security/CleartextLoggingCustomizations.qll

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)