You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spark.apache.org by ho...@apache.org on 2026/09/25 19:20:55 UTC

(spark) branch branch-4.1 updated: [SPARK-59334][CORE] Handle invalid application/worker links

This is an automated email from the ASF dual-hosted git repository.

asf-gitbox-commits pushed a commit to branch branch-4.1
in repository https://gitbox.apache.org/repos/asf/spark.git


The following commit(s) were added to refs/heads/branch-4.1 by this push:
     new 69279f94a897 [SPARK-59334][CORE] Handle invalid application/worker links
69279f94a897 is described below

commit 69279f94a89789a34b0b61464601f59ef054c5f1
Author: Holden Karau <ho...@snowflake.com>
AuthorDate: Fri Sep 25 12:19:59 2026 -0700

    [SPARK-59334][CORE] Handle invalid application/worker links
    
    Drop invalid links rather than break rendering
    
    Application and worker UI addresses come from external registrants and could contain bad/invalid info. Filter it out to prevent the UI from breaking.
    
    No
    
    New UIUtilSuite test
    
    Yes
    Generated-by: Cursor (Kimi K3)
    
    Closes #58622 from holdenk/improve-ui-link-rendering-part2.
    
    Lead-authored-by: Holden Karau <ho...@pigscanfly.ca>
    Co-authored-by: Holden Karau <ho...@snowflake.com>
    Signed-off-by: Holden Karau <ho...@snowflake.com>
    (cherry picked from commit e91d22d3247be55fed37940e32d91c0afc0ab682)
    Signed-off-by: Holden Karau <ho...@snowflake.com>
---
 core/src/main/scala/org/apache/spark/ui/UIUtils.scala  | 18 ++++++++++++++++--
 .../test/scala/org/apache/spark/ui/UIUtilsSuite.scala  | 14 ++++++++++++++
 2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/core/src/main/scala/org/apache/spark/ui/UIUtils.scala b/core/src/main/scala/org/apache/spark/ui/UIUtils.scala
index 71e3356eda20..bc78f0b96110 100644
--- a/core/src/main/scala/org/apache/spark/ui/UIUtils.scala
+++ b/core/src/main/scala/org/apache/spark/ui/UIUtils.scala
@@ -19,7 +19,7 @@ package org.apache.spark.ui
 
 import java.{util => ju}
 import java.lang.{Long => JLong}
-import java.net.{URLDecoder, URLEncoder}
+import java.net.{URI, URISyntaxException, URLDecoder, URLEncoder}
 import java.nio.charset.StandardCharsets.UTF_8
 import java.time.{Instant, ZoneId}
 import java.time.format.DateTimeFormatter
@@ -689,8 +689,22 @@ private[spark] object UIUtils extends Logging {
     if (proxy) {
       val proxyPrefix = sys.props.getOrElse("spark.ui.proxyBase", "")
       proxyPrefix + "/proxy/" + id
-    } else {
+    } else if (isSafeHref(origHref)) {
       origHref
+    } else {
+      // The href may come from an external registrant (e.g. an application's appUiUrl or
+      // a worker's webUiAddress); render anything unrecognized as a dead link.
+      "#"
+    }
+  }
+
+  /** Returns true if the given href is relative or uses the http(s) scheme. */
+  private def isSafeHref(href: String): Boolean = href != null && {
+    try {
+      val scheme = new URI(href).getScheme
+      scheme == null || scheme.equalsIgnoreCase("http") || scheme.equalsIgnoreCase("https")
+    } catch {
+      case _: URISyntaxException => false
     }
   }
 
diff --git a/core/src/test/scala/org/apache/spark/ui/UIUtilsSuite.scala b/core/src/test/scala/org/apache/spark/ui/UIUtilsSuite.scala
index a677f19f5439..1cf7389d011d 100644
--- a/core/src/test/scala/org/apache/spark/ui/UIUtilsSuite.scala
+++ b/core/src/test/scala/org/apache/spark/ui/UIUtilsSuite.scala
@@ -225,4 +225,18 @@ class UIUtilsSuite extends SparkFunSuite {
     assert(cell4 === <td>{"java.lang.RuntimeException"}{UIUtils.detailsUINode(isMultiline = true, e4)}</td>)
   }
   // scalastyle:on line.size.limit
+
+  test("makeHref only renders http(s) or relative URLs as hyperlinks") {
+    // appUiUrl and webUiAddress come from external registrants.
+    assert(UIUtils.makeHref(proxy = false, "app-1", "http://host:4040") === "http://host:4040")
+    assert(UIUtils.makeHref(proxy = false, "app-1", "https://host:4040") === "https://host:4040")
+    assert(UIUtils.makeHref(proxy = false, "app-1", "/relative/path") === "/relative/path")
+    assert(UIUtils.makeHref(proxy = false, "app-1", null) === "#")
+    // A non-http(s) scheme or a malformed URI renders as a dead link.
+    assert(UIUtils.makeHref(proxy = false, "app-1", "javascript:alert(1)") === "#")
+    assert(UIUtils.makeHref(proxy = false, "app-1", "ht tp://bad url") === "#")
+    assert(UIUtils.makeHref(proxy = false, "app-1", "http://host:4040/a b") === "#")
+    // Reverse-proxy mode is unaffected: the href is generated by the master itself.
+    assert(UIUtils.makeHref(proxy = true, "app-1", "javascript:alert(1)").endsWith("/proxy/app-1"))
+  }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@spark.apache.org
For additional commands, e-mail: commits-help@spark.apache.org