yuqi1129 commented on code in PR #13239:
URL: https://github.com/apache/gravitino/pull/13239#discussion_r4048057621
##########
common/src/main/java/org/apache/gravitino/utils/JdbcUrlUtils.java:
##########
@@ -86,23 +87,56 @@ public static void validateJdbcConfig(String driver, String
url, Map<String, Str
Preconditions.checkArgument(StringUtils.isNotBlank(url), "JDBC URL can't
be blank");
String lowerUrl = url.toLowerCase(Locale.ROOT);
- String decodedUrl = recursiveDecode(lowerUrl);
-
- if (decodedUrl.startsWith("jdbc:mysql")) {
- checkUnsafeParameters(decodedUrl, all, UNSAFE_MYSQL_PARAMETERS, "MySQL");
- } else if (decodedUrl.startsWith("jdbc:mariadb")) {
- checkUnsafeParameters(decodedUrl, all, UNSAFE_MYSQL_PARAMETERS,
"MariaDB");
- } else if (decodedUrl.startsWith("jdbc:postgresql")) {
- checkUnsafeParameters(decodedUrl, all, UNSAFE_POSTGRES_PARAMETERS,
"PostgreSQL");
+ List<String> decodedForms = decodedFormsForScan(lowerUrl);
+
+ if (anyFormStartsWith(decodedForms, "jdbc:mysql")) {
+ checkUnsafeParameters(decodedForms, all, UNSAFE_MYSQL_PARAMETERS,
"MySQL");
+ } else if (anyFormStartsWith(decodedForms, "jdbc:mariadb")) {
+ checkUnsafeParameters(decodedForms, all, UNSAFE_MYSQL_PARAMETERS,
"MariaDB");
+ } else if (anyFormStartsWith(decodedForms, "jdbc:postgresql")) {
+ checkUnsafeParameters(decodedForms, all, UNSAFE_POSTGRES_PARAMETERS,
"PostgreSQL");
}
}
- private static void checkUnsafeParameters(
- String url, Map<String, String> config, List<String> unsafeParams,
String dbType) {
+ /**
+ * Returns the decoded forms of a JDBC URL that unsafe-parameter scans must
cover. Drivers such as
+ * MySQL Connector/J decode query tokens independently and ignore the URL
fragment, so a malformed
+ * percent escape in one part of the URL must not stop the scan from
revealing parameter names
+ * hidden behind valid encodings in another part. The returned forms are the
URL decoded until the
+ * first undecodable escape, plus the fully decoded form of the URL with
malformed escapes treated
+ * as literal '{@code %}' characters.
+ *
+ * @param url the JDBC URL, already lower-cased by the caller.
+ * @return the candidate decoded forms, never empty.
+ */
+ public static List<String> decodedFormsForScan(String url) {
+ // Percent-decoding can reintroduce upper-case characters (e.g. "%4a" ->
'J'), so the
+ // returned forms are lower-cased for substring and prefix matching.
+ String stoppedAtMalformed = recursiveDecode(url).toLowerCase(Locale.ROOT);
+ String fullyDecoded =
recursiveDecodeSanitizingEachPass(url).toLowerCase(Locale.ROOT);
+ if (fullyDecoded.equals(stoppedAtMalformed)) {
+ return Collections.singletonList(stoppedAtMalformed);
+ }
+ return Arrays.asList(stoppedAtMalformed, fullyDecoded);
+ }
- // Percent-decoding in recursiveDecode can reintroduce upper-case
characters (e.g. "%4a" ->
- // 'J'), so lower-case again here rather than relying on the pre-decode
lower-casing.
- String lowerUrl = url.toLowerCase(Locale.ROOT);
+ /**
+ * Replaces every '{@code %}' that is not followed by two hex digits with
the escape for a literal
+ * '{@code %}', making the URL decodable by {@link URLDecoder}.
+ */
+ private static String sanitizeMalformedPercentEscapes(String url) {
Review Comment:
The sanitizer is case-sensitive and will fail in the second decoder if the
first round output upper case character.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]