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);