Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
rules:
- id: codevigilant.java.general.input-validation.matcher-replaceall-tainted-replacement
mode: taint
pattern-sources:
- pattern: $MAP.get($KEY)
- pattern: $MAP.getOrDefault($KEY, $DEF)
- pattern: System.getenv($NAME)
- pattern: System.getProperty($NAME)
- pattern: $REQ.getParameter($NAME)
pattern-sinks:
- pattern: $MATCHER.replaceAll($REPL)
- pattern: $MATCHER.appendReplacement($SB, $REPL)
message: |
Detected a non-literal replacement string flowing into
Matcher.replaceAll/appendReplacement. Java replacement strings treat
'$' and '\' as metacharacters: a '$' followed by a digit or '{' is
resolved as a back-reference to a capturing group, so an
attacker-influenced replacement (e.g. a build parameter or environment
value such as '$1') throws an unchecked exception ('No group 1') or
silently substitutes the wrong text, enabling denial of service or
string-manipulation bugs. Wrap the replacement with
Matcher.quoteReplacement() before passing it to the matcher.
metadata:
category: security
cwe: "CWE-74: Improper Neutralization of Special Elements in Output Used by a Downstream Component"
owasp: "A03:2021 - Injection"
confidence: MEDIUM
references:
- https://docs.oracle.com/javase/8/docs/api/java/util/regex/Matcher.html#quoteReplacement-java.lang.String-
source: independent security review
license: MIT
languages: [java]
severity: MEDIUM
9 changes: 9 additions & 0 deletions testcases/java/negative/ReplaceAllNeg.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class ReplaceAllNeg {
public String sanitize(String cmdln) {
Matcher m = Pattern.compile("\\s+").matcher(cmdln);
return m.replaceAll(" ");
}
}
19 changes: 19 additions & 0 deletions testcases/java/positive/ReplaceAllPos.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import java.util.Map;
import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class ReplaceAllPos {
public String expand(String cmdln, Map<String, String> envMap) {
final Pattern expr = Pattern.compile("\\$\\{([A-Za-z_][A-Za-z0-9_]*)\\}");
Matcher matcher = expr.matcher(cmdln);
while (matcher.find()) {
String envValue = envMap.get(matcher.group(1).toUpperCase());
if (envValue == null) {
envValue = "";
}
Matcher subexpr = Pattern.compile(Pattern.quote(matcher.group(0))).matcher(cmdln);
cmdln = subexpr.replaceAll(envValue);
}
return cmdln;
}
}