Merge pull request #20688 from hvitved/java/request-forgery-matches-sanitizer

Java: Treat `x.matches(regexp)` as a sanitizer for request forgery
This commit is contained in:
Tom Hvitved
2025-10-24 14:34:32 +02:00
committed by GitHub
4 changed files with 44 additions and 1 deletions

View File

@@ -164,3 +164,24 @@ private class HostComparisonSanitizer extends RequestForgerySanitizer {
this = DataFlow::BarrierGuard<isHostComparisonSanitizer/3>::getABarrierNode()
}
}
/**
* A qualifier in a call to a `.matches()` method that is a sanitizer for URL redirects.
*
* Matches any method call where the method is named `matches`.
*/
private predicate isMatchesSanitizer(Guard guard, Expr e, boolean branch) {
guard =
any(MethodCall method |
method.getMethod().getName() = "matches" and
e = method.getQualifier() and
branch = true
)
}
/**
* A qualifier in a call to `.matches()` that is a sanitizer for URL redirects.
*/
private class MatchesSanitizer extends RequestForgerySanitizer {
MatchesSanitizer() { this = DataFlow::BarrierGuard<isMatchesSanitizer/3>::getABarrierNode() }
}

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Calls to `String.matches` are now treated as sanitizers for the `java/ssrf` query.

View File

@@ -119,8 +119,26 @@ public class SanitizationTests extends HttpServlet {
String unsafeUri10 = String.format("%s://%s:%s%s", "http", "myserver.com", "80", request.getParameter("baduri10")); // $ Source
HttpRequest unsafer10 = HttpRequest.newBuilder(new URI(unsafeUri10)).build(); // $ Alert
client.send(unsafer10, null); // $ Alert
// GOOD: sanitisation by regexp validation
String param10 = request.getParameter("uri10");
if (param10.matches("[a-zA-Z0-9_-]+")) {
HttpRequest r10 = HttpRequest.newBuilder(new URI(param10)).build();
client.send(r10, null);
}
String param11 = request.getParameter("uri11");
validate(param11);
HttpRequest r11 = HttpRequest.newBuilder(new URI(param11)).build();
client.send(r11, null);
} catch (Exception e) {
// TODO: handle exception
}
}
private void validate(String s) {
if (!s.matches("[a-zA-Z0-9_-]+")) {
throw new IllegalArgumentException("Invalid ID");
}
}
}

View File

@@ -7,7 +7,7 @@
# - What language the change note is for
# - Whether it's a query or library change (the string `src` or `lib`)
# - The name of the change note (in kebab-case)
# - The category of the change.
# - The category of the change (see https://github.com/github/codeql/blob/main/docs/change-notes.md#change-categories).
# The change note will be created in the `{language}/ql/{subdir}/change-notes` directory, where `subdir` is either `src` or `lib`.