Skip to content

Commit df604f0

Browse files
committed
[SPARK-54857][WEBUI][TESTS] Add test ensuring user name and app name in historypage get escaped
### What changes were proposed in this pull request? This PR proposes to add tests for SPARK-53337 and SPARK-54624. ### Why are the changes needed? To ensure user name and app name in historypage get escaped. ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? Add new test. ### Was this patch authored or co-authored using generative AI tooling? No. Closes #53628 from sarutak/add-xss-test. Authored-by: Kousuke Saruta <[email protected]> Signed-off-by: Kousuke Saruta <[email protected]>
1 parent 578ee01 commit df604f0

File tree

10 files changed

+108
-15
lines changed

10 files changed

+108
-15
lines changed

core/src/test/resources/HistoryServerExpectations/application_list_json_expectation.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,19 @@
11
[ {
2+
"attempts" : [ {
3+
"appSparkVersion" : "4.2.0-SNAPSHOT",
4+
"completed" : true,
5+
"duration" : 2006,
6+
"endTime" : "2025-12-27T14:15:12.221GMT",
7+
"endTimeEpoch" : 1766844912221,
8+
"lastUpdated" : "",
9+
"lastUpdatedEpoch" : 0,
10+
"sparkUser" : "<script>alert('XSS')</script>",
11+
"startTime" : "2025-12-27T14:15:10.215GMT",
12+
"startTimeEpoch" : 1766844910215
13+
} ],
14+
"id" : "local-1766844910796",
15+
"name" : "<script>alert('XSS')</script>"
16+
}, {
217
"attempts" : [ {
318
"appSparkVersion" : "3.3.0-SNAPSHOT",
419
"completed" : true,

core/src/test/resources/HistoryServerExpectations/completed_app_list_json_expectation.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,19 @@
11
[ {
2+
"attempts" : [ {
3+
"appSparkVersion" : "4.2.0-SNAPSHOT",
4+
"completed" : true,
5+
"duration" : 2006,
6+
"endTime" : "2025-12-27T14:15:12.221GMT",
7+
"endTimeEpoch" : 1766844912221,
8+
"lastUpdated" : "",
9+
"lastUpdatedEpoch" : 0,
10+
"sparkUser" : "<script>alert('XSS')</script>",
11+
"startTime" : "2025-12-27T14:15:10.215GMT",
12+
"startTimeEpoch" : 1766844910215
13+
} ],
14+
"id" : "local-1766844910796",
15+
"name" : "<script>alert('XSS')</script>"
16+
}, {
217
"attempts" : [ {
318
"appSparkVersion" : "3.3.0-SNAPSHOT",
419
"completed" : true,

core/src/test/resources/HistoryServerExpectations/limit_app_list_json_expectation.json

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,19 @@
11
[ {
2+
"attempts" : [ {
3+
"appSparkVersion" : "4.2.0-SNAPSHOT",
4+
"completed" : true,
5+
"duration" : 2006,
6+
"endTime" : "2025-12-27T14:15:12.221GMT",
7+
"endTimeEpoch" : 1766844912221,
8+
"lastUpdated" : "",
9+
"lastUpdatedEpoch" : 0,
10+
"sparkUser" : "<script>alert('XSS')</script>",
11+
"startTime" : "2025-12-27T14:15:10.215GMT",
12+
"startTimeEpoch" : 1766844910215
13+
} ],
14+
"id" : "local-1766844910796",
15+
"name" : "<script>alert('XSS')</script>"
16+
}, {
217
"attempts" : [ {
318
"appSparkVersion" : "3.3.0-SNAPSHOT",
419
"completed" : true,
@@ -28,19 +43,4 @@
2843
} ],
2944
"id" : "application_1628109047826_1317105",
3045
"name" : "Spark shell"
31-
}, {
32-
"attempts" : [ {
33-
"appSparkVersion" : "3.1.0-SNAPSHOT",
34-
"completed" : true,
35-
"duration" : 363996,
36-
"endTime" : "2020-07-07T03:17:04.231GMT",
37-
"endTimeEpoch" : 1594091824231,
38-
"lastUpdated" : "",
39-
"lastUpdatedEpoch" : 0,
40-
"sparkUser" : "terryk",
41-
"startTime" : "2020-07-07T03:11:00.235GMT",
42-
"startTimeEpoch" : 1594091460235
43-
} ],
44-
"id" : "app-20200706201101-0003",
45-
"name" : "Spark shell"
4646
} ]

core/src/test/resources/HistoryServerExpectations/minDate_app_list_json_expectation.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,19 @@
11
[ {
2+
"attempts" : [ {
3+
"appSparkVersion" : "4.2.0-SNAPSHOT",
4+
"completed" : true,
5+
"duration" : 2006,
6+
"endTime" : "2025-12-27T14:15:12.221GMT",
7+
"endTimeEpoch" : 1766844912221,
8+
"lastUpdated" : "",
9+
"lastUpdatedEpoch" : 0,
10+
"sparkUser" : "<script>alert('XSS')</script>",
11+
"startTime" : "2025-12-27T14:15:10.215GMT",
12+
"startTimeEpoch" : 1766844910215
13+
} ],
14+
"id" : "local-1766844910796",
15+
"name" : "<script>alert('XSS')</script>"
16+
}, {
217
"attempts" : [ {
318
"appSparkVersion" : "3.3.0-SNAPSHOT",
419
"completed" : true,

core/src/test/resources/HistoryServerExpectations/minEndDate_app_list_json_expectation.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,19 @@
11
[ {
2+
"attempts" : [ {
3+
"appSparkVersion" : "4.2.0-SNAPSHOT",
4+
"completed" : true,
5+
"duration" : 2006,
6+
"endTime" : "2025-12-27T14:15:12.221GMT",
7+
"endTimeEpoch" : 1766844912221,
8+
"lastUpdated" : "",
9+
"lastUpdatedEpoch" : 0,
10+
"sparkUser" : "<script>alert('XSS')</script>",
11+
"startTime" : "2025-12-27T14:15:10.215GMT",
12+
"startTimeEpoch" : 1766844910215
13+
} ],
14+
"id" : "local-1766844910796",
15+
"name" : "<script>alert('XSS')</script>"
16+
}, {
217
"attempts" : [ {
318
"appSparkVersion" : "3.3.0-SNAPSHOT",
419
"completed" : true,

core/src/test/resources/spark-events/eventlog_v2_local-1766844910796/appstatus_local-1766844910796

Whitespace-only changes.

core/src/test/resources/spark-events/eventlog_v2_local-1766844910796/events_1_local-1766844910796

Lines changed: 15 additions & 0 deletions
Large diffs are not rendered by default.

core/src/test/scala/org/apache/spark/deploy/history/HistoryServerSuite.scala

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,23 @@ abstract class HistoryServerSuite extends SparkFunSuite with BeforeAndAfter with
390390
assert(response.contains(SPARK_VERSION))
391391
}
392392

393+
test("SPARK-54857: XSS prevention in application and user names") {
394+
implicit val formats = org.json4s.DefaultFormats
395+
396+
val appId = "local-1766844910796"
397+
val response = getUrl(s"applications/$appId")
398+
val app = JsonMethods.parse(response)
399+
400+
// Verify that malicious content is present in JSON (not escaped at API level)
401+
(app \ "name").extract[String] should be ("<script>alert('XSS')</script>")
402+
val attempt = (app \ "attempts")(0)
403+
(attempt \ "sparkUser").extract[String] should be ("<script>alert('XSS')</script>")
404+
405+
// Verify that the history page HTML properly escapes the content
406+
val historyPage = HistoryServerSuite.getUrl(buildPageAttemptUrl(appId, None))
407+
historyPage should not include "<script>alert('XSS')</script>"
408+
}
409+
393410
/**
394411
* Verify that the security manager needed for the history server can be instantiated
395412
* when `spark.authenticate` is `true`, rather than raise an `IllegalArgumentException`.

dev/.rat-excludes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ local-1430917381534
8888
local-1430917381535_1
8989
local-1430917381535_2
9090
local-1642039451826
91+
eventlog_v2_local-1766844910796
9192
DESCRIPTION
9293
NAMESPACE
9394
test_support/*

0 commit comments

Comments
 (0)