diff --git a/core/src/main/java/hudson/model/Cause.java b/core/src/main/java/hudson/model/Cause.java
index a9dafcb59b..b8b847356a 100644
--- a/core/src/main/java/hudson/model/Cause.java
+++ b/core/src/main/java/hudson/model/Cause.java
@@ -486,12 +486,12 @@ public abstract class Cause {
public String getShortDescription() {
if(note != null) {
try {
- return Messages.Cause_RemoteCause_ShortDescriptionWithNote(addr, Jenkins.get().getMarkupFormatter().translate(note));
+ return Messages.Cause_RemoteCause_ShortDescriptionWithNote(Util.xmlEscape(addr), Jenkins.get().getMarkupFormatter().translate(note));
} catch (IOException x) {
// ignore
}
}
- return Messages.Cause_RemoteCause_ShortDescription(addr);
+ return Messages.Cause_RemoteCause_ShortDescription(Util.xmlEscape(addr));
}
@Exported(visibility = 3)
diff --git a/test/src/test/java/hudson/model/CauseSecurity1960Test.java b/test/src/test/java/hudson/model/CauseSecurity1960Test.java
new file mode 100644
index 0000000000..b1be6d2036
--- /dev/null
+++ b/test/src/test/java/hudson/model/CauseSecurity1960Test.java
@@ -0,0 +1,32 @@
+package hudson.model;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.jvnet.hudson.test.Issue;
+import org.jvnet.hudson.test.JenkinsRule;
+import org.jvnet.hudson.test.recipes.LocalData;
+import org.xml.sax.SAXException;
+
+import java.io.IOException;
+
+// TODO merge into CauseTest after release
+public class CauseSecurity1960Test {
+ @Rule
+ public JenkinsRule j = new JenkinsRule();
+
+ @Test
+ @Issue("SECURITY-1960")
+ @LocalData
+ public void xssInRemoteCause() throws IOException, SAXException {
+ final Item item = j.jenkins.getItemByFullName("fs");
+ Assert.assertTrue(item instanceof FreeStyleProject);
+ FreeStyleProject fs = (FreeStyleProject) item;
+ final FreeStyleBuild build = fs.getBuildByNumber(1);
+
+ final JenkinsRule.WebClient wc = j.createWebClient();
+ final String content = wc.getPage(build).getWebResponse().getContentAsString();
+ Assert.assertFalse(content.contains("Started by remote host
+
+
+
+
+
+
+ <img src=x onerror=alert(1)>
+ note
+
+ 1
+
+
+
+
+ 4
+ 1595937941553
+ 1595937941557
+ SUCCESS
+ 2
+ UTF-8
+ false
+
+ /var/jenkins_home/workspace/fs
+ 2.249
+
+
+
\ No newline at end of file
diff --git a/test/src/test/resources/hudson/model/CauseSecurity1960Test/jobs/fs/config.xml b/test/src/test/resources/hudson/model/CauseSecurity1960Test/jobs/fs/config.xml
new file mode 100644
index 0000000000..087bf4e467
--- /dev/null
+++ b/test/src/test/resources/hudson/model/CauseSecurity1960Test/jobs/fs/config.xml
@@ -0,0 +1,18 @@
+
+
+
+
+ false
+
+
+ true
+ false
+ false
+ false
+ test
+
+ false
+
+
+
+
\ No newline at end of file
diff --git a/war/src/main/js/add-item.js b/war/src/main/js/add-item.js
index b82a94c610..762a6e64ae 100644
--- a/war/src/main/js/add-item.js
+++ b/war/src/main/js/add-item.js
@@ -59,7 +59,7 @@ $.when(getItems()).done(function(data) {
function activateValidationMessage(messageId, context, message) {
if (message !== undefined && message !== '') {
- $(messageId, context).html('» ' + message);
+ $(messageId, context).text('ยป ' + message);
}
cleanValidationMessages(context);
hideInputHelp(context);