From cb7cbaa25814da47f222a72f415f22e45904e5ea Mon Sep 17 00:00:00 2001 From: wuyangfan Date: Mon, 25 May 2026 11:05:50 +0800 Subject: [PATCH] Fix isDotDot to recognize ..%2e and %2e.. path segments HttpUrl.resolve() left ..%2e and %2e.. in the encoded path instead of normalizing them like other percent-encoded dot-dot forms. This could bypass path-prefix sandbox checks that rely on encodedPath(). Fixes #9451 Co-authored-by: Cursor --- okhttp/src/commonJvmAndroid/kotlin/okhttp3/HttpUrl.kt | 4 +++- okhttp/src/jvmTest/kotlin/okhttp3/HttpUrlTest.kt | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/okhttp/src/commonJvmAndroid/kotlin/okhttp3/HttpUrl.kt b/okhttp/src/commonJvmAndroid/kotlin/okhttp3/HttpUrl.kt index 646c698437e2..fbe6d9b27305 100644 --- a/okhttp/src/commonJvmAndroid/kotlin/okhttp3/HttpUrl.kt +++ b/okhttp/src/commonJvmAndroid/kotlin/okhttp3/HttpUrl.kt @@ -1594,7 +1594,9 @@ class HttpUrl private constructor( input == ".." || input.equals("%2e.", ignoreCase = true) || input.equals(".%2e", ignoreCase = true) || - input.equals("%2e%2e", ignoreCase = true) + input.equals("%2e%2e", ignoreCase = true) || + input.equals("..%2e", ignoreCase = true) || + input.equals("%2e..", ignoreCase = true) /** * Cuts this string up into alternating parameter names and values. This divides a query string diff --git a/okhttp/src/jvmTest/kotlin/okhttp3/HttpUrlTest.kt b/okhttp/src/jvmTest/kotlin/okhttp3/HttpUrlTest.kt index 9ada0b3ee425..59fca61ec78c 100644 --- a/okhttp/src/jvmTest/kotlin/okhttp3/HttpUrlTest.kt +++ b/okhttp/src/jvmTest/kotlin/okhttp3/HttpUrlTest.kt @@ -973,6 +973,10 @@ open class HttpUrlTest { assertThat(base.resolve("%2e.")).isEqualTo(parse("http://host/a/")) assertThat(base.resolve(".%2e")).isEqualTo(parse("http://host/a/")) assertThat(base.resolve("%2e%2e")).isEqualTo(parse("http://host/a/")) + assertThat(base.resolve("..%2e")).isEqualTo(parse("http://host/a/")) + assertThat(base.resolve("%2e..")).isEqualTo(parse("http://host/a/")) + assertThat(base.resolve("..%2E")).isEqualTo(parse("http://host/a/")) + assertThat(base.resolve("%2E..")).isEqualTo(parse("http://host/a/")) assertThat(base.resolve("%2E")).isEqualTo(parse("http://host/a/b/")) assertThat(base.resolve("%2e")).isEqualTo(parse("http://host/a/b/")) }