Skip to content

Commit

Permalink
[SECURITY-2779]
Browse files Browse the repository at this point in the history
  • Loading branch information
daniel-beck authored and jenkinsci-cert-ci committed Jun 9, 2022
1 parent 8080ec4 commit f71495a
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 1 deletion.
2 changes: 1 addition & 1 deletion core/src/main/resources/lib/form/helpLink.jelly
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ THE SOFTWARE.
</st:documentation>
<j:choose>
<j:when test="${attrs.url!=null}">
<j:set var="altText" value="${attrs.featureName != null ? '%Help for feature:' + ' ' + attrs.featureName : '%Help'}" />
<j:set var="altText" value="${attrs.featureName != null ? '%Help for feature:' + ' ' + h.escape(attrs.featureName) : '%Help'}" />
<a href="#" class="jenkins-help-button" tooltip="${altText}" helpURL="${rootURL}${attrs.url}">
<!-- .jenkins-help-button span element is required as it's restyled in CSS -->
<span>?</span>
Expand Down
84 changes: 84 additions & 0 deletions test/src/test/java/jenkins/security/Security2779Test.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package jenkins.security;

import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;

import com.gargoylesoftware.htmlunit.AlertHandler;
import com.gargoylesoftware.htmlunit.ScriptResult;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import hudson.model.UnprotectedRootAction;
import java.util.Arrays;
import java.util.Collection;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.TestExtension;

@RunWith(Parameterized.class)
public class Security2779Test {
public static final String URL_NAME = "security2779";
private final String selector;
@Rule
public JenkinsRule j = new JenkinsRule();

@Parameterized.Parameters
public static Collection<String> getSelectors() {
return Arrays.asList("#link-panel a", "#icon-panel svg");
}

public Security2779Test(String selector) {
this.selector = selector;
}

@Test
public void noXssInHelp() throws Exception {
final AtomicInteger alerts = new AtomicInteger();
final JenkinsRule.WebClient webClient = j.createWebClient();
webClient.setAlertHandler((AlertHandler) (p, s) -> alerts.addAndGet(1));
final HtmlPage page = webClient.goTo(URL_NAME);
final ScriptResult eventScript = page.executeJavaScript("document.querySelector('" + selector + "').dispatchEvent(new Event('mouseover'))");
final Object eventResult = eventScript.getJavaScriptResult();
assertThat(eventResult, instanceOf(boolean.class));
Assert.assertTrue((boolean) eventResult);
webClient.waitForBackgroundJavaScript(2000);
Assert.assertEquals(0, alerts.get());

final ScriptResult innerHtmlScript = page.executeJavaScript("document.querySelector('#tt').innerHTML");
Object jsResult = innerHtmlScript.getJavaScriptResult();
assertThat(jsResult, instanceOf(String.class));
String jsResultString = (String) jsResult;

// assert leading space to identify unintentional double-escaping (&amp;lt;) as test failure
assertThat("tooltip does not contain dangerous HTML", jsResultString, not(containsString(" <img src=x")));
assertThat("tooltip contains safe text", jsResultString, containsString(" &lt;img src=x"));
}

@TestExtension
public static class ViewHolder implements UnprotectedRootAction {

@Override
public String getIconFileName() {
return null;
}

@Override
public String getDisplayName() {
return null;
}

@Override
public String getUrlName() {
return URL_NAME;
}

public String getFeatureName() {
return " <img src=x onerror=alert(1)>";
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:l="/lib/layout" xmlns:f="/lib/form">
<l:layout title="help">
<l:main-panel>
<div id="link-panel">
<f:helpLink featureName="${it.featureName}" url="foo" />
</div>
<div id="icon-panel">
<l:helpIcon tooltip="${it.featureName}" />
</div>
</l:main-panel>
</l:layout>
</j:jelly>

0 comments on commit f71495a

Please # to comment.