Skip to content

Commit 6282385

Browse files
committed
Check replacer will replace \r or \n
Implementation copied from string break.
1 parent b8417e0 commit 6282385

File tree

1 file changed

+48
-7
lines changed

1 file changed

+48
-7
lines changed

go/ql/lib/semmle/go/security/LogInjectionCustomizations.qll

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,17 +59,52 @@ module LogInjection {
5959
}
6060
}
6161

62+
/**
63+
* A call to `strings.NewReplacer`.
64+
*/
65+
class StringsNewReplacerCall extends DataFlow::CallNode {
66+
StringsNewReplacerCall() { this.getTarget().hasQualifiedName("strings", "NewReplacer") }
67+
68+
/**
69+
* Gets an argument to this call corresponding to a string that will be
70+
* replaced.
71+
*/
72+
DataFlow::Node getAReplacedArgument() { exists(int n | n % 2 = 0 and result = getArgument(n)) }
73+
}
74+
75+
/**
76+
* A configuration for tracking flow from a call to `strings.NewReplacer` to
77+
* the receiver of a call to `strings.Replacer.Replace` or
78+
* `strings.Replacer.WriteString`.
79+
*/
80+
class StringsNewReplacerConfiguration extends DataFlow2::Configuration {
81+
StringsNewReplacerConfiguration() { this = "StringsNewReplacerConfiguration" }
82+
83+
override predicate isSource(DataFlow::Node source) { source instanceof StringsNewReplacerCall }
84+
85+
override predicate isSink(DataFlow::Node sink) {
86+
exists(DataFlow::MethodCallNode call |
87+
sink = call.getReceiver() and
88+
call.getTarget().hasQualifiedName("strings", "Replacer", ["Replace", "WriteString"])
89+
)
90+
}
91+
}
92+
6293
/**
6394
* A call to `strings.Replacer.Replace`, considered as a sanitizer for log
6495
* injection.
6596
*/
6697
class ReplacerReplaceSanitizer extends Sanitizer {
6798
ReplacerReplaceSanitizer() {
68-
exists(DataFlow::MethodCallNode call |
69-
call.(DataFlow::MethodCallNode)
70-
.getTarget()
71-
.hasQualifiedName("strings", "Replacer", "Replace") and
72-
this = call.getResult()
99+
exists(
100+
StringsNewReplacerConfiguration config, DataFlow::Node source, DataFlow::Node sink,
101+
DataFlow::MethodCallNode call
102+
|
103+
config.hasFlow(source, sink) and
104+
call.getTarget().hasQualifiedName("strings", "Replacer", "Replace") and
105+
sink = call.getReceiver() and
106+
this = call.getResult() and
107+
source.(StringsNewReplacerCall).getAReplacedArgument().getStringValue() = ["\r", "\n"]
73108
)
74109
}
75110
}
@@ -80,9 +115,15 @@ module LogInjection {
80115
*/
81116
class ReplacerWriteStringSanitizer extends Sanitizer {
82117
ReplacerWriteStringSanitizer() {
83-
exists(DataFlow::MethodCallNode call |
118+
exists(
119+
StringsNewReplacerConfiguration config, DataFlow::Node source, DataFlow::Node sink,
120+
DataFlow::MethodCallNode call
121+
|
122+
config.hasFlow(source, sink) and
84123
call.getTarget().hasQualifiedName("strings", "Replacer", "WriteString") and
85-
this = call.getArgument(1)
124+
sink = call.getReceiver() and
125+
this = call.getArgument(1) and
126+
source.(StringsNewReplacerCall).getAReplacedArgument().getStringValue() = ["\r", "\n"]
86127
)
87128
}
88129
}

0 commit comments

Comments
 (0)