Skip to content

Commit c43d0fc

Browse files
committed
[SECURITY-2760]
1 parent f69ed5d commit c43d0fc

File tree

5 files changed

+52
-4
lines changed

5 files changed

+52
-4
lines changed

src/main/resources/hudson/tasks/junit/CaseResult/list.jelly

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ THE SOFTWARE.
4747
<st:include it="${badge}" page="badge.jelly" optional="true"/>
4848
</j:forEach>
4949
</td>
50-
<td class="pane" style="text-align:left"><j:out value="${test.description}"/></td>
50+
<td class="pane" style="text-align:left"><j:out value="${app.markupFormatter.translate(test.description)}"/></td>
5151
<td class="pane no-wrap" style="text-align:left" data="${test.duration}">${test.durationString}</td>
5252
<td class="pane">
5353
<j:set var="pst" value="${test.status}" />

src/main/resources/hudson/tasks/junit/ClassResult/list.jelly

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ THE SOFTWARE.
4646
<st:include it="${badge}" page="badge.jelly" optional="true"/>
4747
</j:forEach>
4848
</td>
49-
<td class="pane" style="text-align:right"><j:out value="${p.description}"/></td>
49+
<td class="pane" style="text-align:right"><j:out value="${app.markupFormatter.translate(p.description)}"/></td>
5050
<td class="pane no-wrap" style="text-align:right" data="${p.duration}">${p.durationString}</td>
5151
<td class="pane" style="text-align:right">${p.failCount}</td>
5252
<td class="pane" style="text-align:right">${p.skipCount}</td>

src/main/resources/hudson/tasks/junit/History/index.jelly

+1-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ THE SOFTWARE.
9696
<a href="${app.rootUrl}${item.url}">${item.fullDisplayName}</a>
9797
</td>
9898
<j:if test="${historySummary.descriptionAvailable}">
99-
<td class="pane" style="text-align:right"><j:out value="${item.description}"/></td>
99+
<td class="pane" style="text-align:right"><j:out value="${app.markupFormatter.translate(item.description)}"/></td>
100100
</j:if>
101101
<td class="pane no-wrap" style="text-align:right" data="${item.duration}">${item.durationString}</td>
102102
<td class="pane" style="text-align:right">${item.failCount}</td>

src/main/resources/hudson/tasks/test/MetaTabulatedResult/list.jelly

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ THE SOFTWARE.
4646
<st:include it="${badge}" page="badge.jelly" optional="true"/>
4747
</j:forEach>
4848
</td>
49-
<td class="pane" style="text-align:right"><j:out value="${p.description}"/></td>
49+
<td class="pane" style="text-align:right"><j:out value="${app.markupFormatter.translate(p.description)}"/></td>
5050
<td class="pane no-wrap" style="text-align:right" data="${p.duration}">${p.durationString}</td>
5151
<td class="pane" style="text-align:right">${p.failCount}</td>
5252
<td class="pane" style="text-align:right">${p.skipCount}</td>

src/test/java/hudson/tasks/junit/HistoryTest.java

+48
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,28 @@
2323
*/
2424
package hudson.tasks.junit;
2525

26+
import com.gargoylesoftware.htmlunit.AlertHandler;
27+
import com.gargoylesoftware.htmlunit.Page;
28+
import com.gargoylesoftware.htmlunit.html.HtmlPage;
29+
import com.gargoylesoftware.htmlunit.html.HtmlTable;
30+
import com.gargoylesoftware.htmlunit.html.HtmlTableCell;
2631
import hudson.model.FreeStyleBuild;
2732
import hudson.model.FreeStyleProject;
2833
import hudson.model.Project;
2934
import hudson.model.Result;
3035
import org.junit.Before;
3136
import org.junit.Rule;
3237
import org.junit.Test;
38+
import org.jvnet.hudson.test.Issue;
3339
import org.jvnet.hudson.test.JenkinsRule;
3440
import org.jvnet.hudson.test.recipes.LocalData;
3541

3642
import java.util.List;
43+
import java.util.Optional;
3744

3845
import static org.junit.Assert.assertEquals;
3946
import static org.junit.Assert.assertNotNull;
47+
import static org.junit.Assert.assertNull;
4048
import static org.junit.Assert.assertTrue;
4149

4250
public class HistoryTest {
@@ -113,4 +121,44 @@ public void testFailedSince() throws Exception {
113121
assertTrue("eleanor failed", !eleanorCase.isPassed());
114122
assertEquals("eleanor has failed since build 3", 3, eleanorCase.getFailedSince());
115123
}
124+
125+
@LocalData
126+
@Test @Issue("SECURITY-2760")
127+
public void testXSS() throws Exception {
128+
assertNotNull("project should exist", project);
129+
130+
FreeStyleBuild build4 = project.getBuildByNumber(4);
131+
TestResult tr = build4.getAction(TestResultAction.class).getResult();
132+
133+
tr.setDescription("<script>alert(\"<XSS>\")</script>");
134+
build4.save(); //Might be unnecessary
135+
136+
try (final JenkinsRule.WebClient webClient = rule.createWebClient()) {
137+
Alerter alerter = new Alerter();
138+
webClient.setJavaScriptEnabled(true);
139+
webClient.getOptions().setThrowExceptionOnScriptError(false); //HtmlUnit finds a syntax error in bootstrap 5
140+
webClient.setAlertHandler(alerter); //This catches any alert dialog popup
141+
142+
final HtmlPage page = webClient.getPage(build4, "testReport/history/");
143+
assertNull(alerter.message); //No alert dialog popped up
144+
assertNull(alerter.page);
145+
final HtmlTable table = (HtmlTable) page.getElementById("testresult");
146+
final Optional<HtmlTableCell> descr = table.getRows().stream().flatMap(row -> row.getCells().stream())
147+
.filter(cell -> cell.getTextContent().equals("<script>alert(\"<XSS>\")</script>")) //cell.getTextContent() seems to translate back from &gt; to < etc.
148+
.findFirst();
149+
assertTrue("Should have found the description", descr.isPresent());
150+
}
151+
}
152+
153+
static class Alerter implements AlertHandler {
154+
155+
Page page = null;
156+
String message = null;
157+
158+
@Override
159+
public void handleAlert(final Page page, final String message) {
160+
this.page = page;
161+
this.message = message;
162+
}
163+
}
116164
}

0 commit comments

Comments
 (0)