msrb pushed to jenkins-matrix-project-plugin (f21). "Fix SECURITY-125 (..more)"
notifications at fedoraproject.org
notifications at fedoraproject.org
Wed Apr 1 16:37:16 UTC 2015
>From 7c978515519cbaf49b7c26b65f48bfe7be97d6bd Mon Sep 17 00:00:00 2001
From: Michal Srb <msrb at redhat.com>
Date: Sun, 29 Mar 2015 16:22:23 +0200
Subject: Fix SECURITY-125
- Resolves: CVE-2015-1806
diff --git a/0001-Fix-SECURITY-125.patch b/0001-Fix-SECURITY-125.patch
new file mode 100644
index 0000000..cf36697
--- /dev/null
+++ b/0001-Fix-SECURITY-125.patch
@@ -0,0 +1,284 @@
+From 002668ed111a5642110932154bab6c5adbdf709c Mon Sep 17 00:00:00 2001
+From: Michal Srb <msrb at redhat.com>
+Date: Sun, 29 Mar 2015 16:15:20 +0200
+Subject: [PATCH] Fix SECURITY-125
+
+---
+ pom.xml | 7 +++-
+ src/main/java/hudson/matrix/Combination.java | 14 -------
+ src/main/java/hudson/matrix/FilterScript.java | 48 ++++++++++++++--------
+ .../CombinationFilterUsingBuildParamsTest.java | 7 +++-
+ src/test/java/hudson/matrix/CombinationTest.java | 6 +--
+ src/test/java/hudson/matrix/MatrixTest.java | 37 +++++++++++++++++
+ 6 files changed, 83 insertions(+), 36 deletions(-)
+
+diff --git a/pom.xml b/pom.xml
+index 5d7a058..12dcffd 100644
+--- a/pom.xml
++++ b/pom.xml
+@@ -3,7 +3,7 @@
+ <parent>
+ <groupId>org.jenkins-ci.plugins</groupId>
+ <artifactId>plugin</artifactId>
+- <version>1.561</version>
++ <version>1.590</version>
+ </parent>
+ <artifactId>matrix-project</artifactId>
+ <version>1.4</version>
+@@ -72,6 +72,11 @@
+ </exclusion>
+ </exclusions>
+ </dependency>
++ <dependency>
++ <groupId>org.jenkins-ci.plugins</groupId>
++ <artifactId>script-security</artifactId>
++ <version>1.13</version>
++ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+diff --git a/src/main/java/hudson/matrix/Combination.java b/src/main/java/hudson/matrix/Combination.java
+index 9ce0a4d..35d3458 100644
+--- a/src/main/java/hudson/matrix/Combination.java
++++ b/src/main/java/hudson/matrix/Combination.java
+@@ -248,18 +248,4 @@ public final class Combination extends TreeMap<String,String> implements Compara
+ public String remove(Object key) {
+ throw new UnsupportedOperationException();
+ }
+-
+- /**
+- * Duck-typing for boolean expressions.
+- *
+- * @see Combination#evalGroovyExpression(AxisList,String)
+- */
+- public static final class BooleanCategory {
+- /**
+- * x -> y
+- */
+- public static Boolean implies(Boolean lhs, Boolean rhs) {
+- return !lhs || rhs;
+- }
+- }
+ }
+diff --git a/src/main/java/hudson/matrix/FilterScript.java b/src/main/java/hudson/matrix/FilterScript.java
+index f43cfcd..564fe49 100644
+--- a/src/main/java/hudson/matrix/FilterScript.java
++++ b/src/main/java/hudson/matrix/FilterScript.java
+@@ -3,14 +3,23 @@ package hudson.matrix;
+ import groovy.lang.Binding;
+ import groovy.lang.GroovyShell;
+ import groovy.lang.Script;
++import hudson.Extension;
+ import hudson.Util;
+-import hudson.matrix.Combination.BooleanCategory;
+ import hudson.matrix.MatrixBuild.MatrixBuildExecution;
+ import hudson.model.ParameterValue;
+ import hudson.model.ParametersAction;
+
++import java.io.IOException;
+ import java.util.Map;
+
++import org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException;
++import org.jenkinsci.plugins.scriptsecurity.sandbox.Whitelist;
++import org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.GroovySandbox;
++import org.jenkinsci.plugins.scriptsecurity.sandbox.whitelists.ProxyWhitelist;
++import org.jenkinsci.plugins.scriptsecurity.sandbox.whitelists.StaticWhitelist;
++import org.jenkinsci.plugins.scriptsecurity.scripts.ApprovalContext;
++import org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval;
++
+ import static java.lang.Boolean.*;
+
+ /**
+@@ -31,9 +40,13 @@ class FilterScript {
+ * @param context
+ * Variables the script will see.
+ */
+- boolean evaluate(Binding context) {
++ private boolean evaluate(Binding context) {
+ script.setBinding(context);
+- return TRUE.equals(script.run());
++ try {
++ return TRUE.equals(GroovySandbox.run(script, Whitelist.all()));
++ } catch (RejectedAccessException x) {
++ throw ScriptApproval.get().accessRejected(x, ApprovalContext.create());
++ }
+ }
+
+ /**
+@@ -59,7 +72,7 @@ class FilterScript {
+ /**
+ * Applies the filter to the specified combination in the context of {@code context}.
+ */
+- public boolean apply(MatrixBuildExecution context, Combination combination) {
++ public final boolean apply(MatrixBuildExecution context, Combination combination) {
+ return apply(context.getProject().getAxes(), combination, getConfiguredBinding(context));
+ }
+
+@@ -100,25 +113,18 @@ class FilterScript {
+ if (Util.fixEmptyAndTrim(expression)==null)
+ return defaultScript;
+
+- GroovyShell shell = new GroovyShell(FilterScript.class.getClassLoader());
++ GroovyShell shell = new GroovyShell(GroovySandbox.createSecureClassLoader(FilterScript.class.getClassLoader()), new Binding(), GroovySandbox.createSecureCompilerConfiguration());
+
+- return new FilterScript(shell.parse("use("+BooleanCategory.class.getName().replace('$','.')+") {"+expression+"}"));
++ return new FilterScript(shell.parse(expression));
+ }
+
+- private static final Script EMPTY = new Script() {
+- @Override
+- public Object run() {
+- return true;
+- }
+- };
+-
+ /**
+ * Constant that always applies to any combination.
+ * @since 1.541
+ */
+- /*package*/ static final FilterScript ACCEPT_ALL = new FilterScript(EMPTY) {
++ /*package*/ static final FilterScript ACCEPT_ALL = new FilterScript(null) {
+ @Override
+- public boolean apply(MatrixBuildExecution context, Combination combination) {
++ public boolean apply(AxisList axes, Combination combination, Binding binding) {
+ return true;
+ }
+ };
+@@ -127,10 +133,18 @@ class FilterScript {
+ * Constant that does not apply to any combination.
+ * @since 1.541
+ */
+- /*package*/ static final FilterScript REJECT_ALL = new FilterScript(EMPTY) {
++ /*package*/ static final FilterScript REJECT_ALL = new FilterScript(null) {
+ @Override
+- public boolean apply(MatrixBuildExecution context, Combination combination) {
++ public boolean apply(AxisList axes, Combination combination, Binding binding) {
+ return false;
+ }
+ };
++
++ // TODO JENKINS-25804: harmless generic methods like this should be whitelisted in script-security
++ @Extension
++ public static class ImpliesWhitelist extends ProxyWhitelist {
++ public ImpliesWhitelist() throws IOException {
++ super(new StaticWhitelist("staticMethod org.codehaus.groovy.runtime.DefaultGroovyMethods implies java.lang.Boolean java.lang.Boolean"));
++ }
++ }
+ }
+diff --git a/src/test/java/hudson/matrix/CombinationFilterUsingBuildParamsTest.java b/src/test/java/hudson/matrix/CombinationFilterUsingBuildParamsTest.java
+index a302c7e..15b5de1 100644
+--- a/src/test/java/hudson/matrix/CombinationFilterUsingBuildParamsTest.java
++++ b/src/test/java/hudson/matrix/CombinationFilterUsingBuildParamsTest.java
+@@ -53,6 +53,8 @@ import java.util.Map;
+ import jenkins.model.Jenkins;
+
+ import org.apache.commons.io.output.ByteArrayOutputStream;
++import org.jenkinsci.plugins.scriptsecurity.sandbox.Whitelist;
++import org.jenkinsci.plugins.scriptsecurity.sandbox.whitelists.BlanketWhitelist;
+ import org.junit.Before;
+ import org.junit.Test;
+ import org.junit.runner.RunWith;
+@@ -70,7 +72,8 @@ import org.powermock.modules.junit4.PowerMockRunner;
+ * @author ogondza
+ */
+ @RunWith(PowerMockRunner.class)
+- at PrepareForTest( {Jenkins.class, MatrixBuildListener.class, MatrixProject.class, AbstractItem.class})
++
++ at PrepareForTest({Jenkins.class, MatrixBuildListener.class, MatrixProject.class, AbstractItem.class, Whitelist.class})
+ public class CombinationFilterUsingBuildParamsTest {
+
+ /**
+@@ -239,6 +242,8 @@ public class CombinationFilterUsingBuildParamsTest {
+ PowerMockito.mockStatic(Jenkins.class);
+ when(Jenkins.getInstance()).thenReturn(jenkins);
+ when(jenkins.getNodes()).thenReturn(new ArrayList<Node>());
++ PowerMockito.mockStatic(Whitelist.class);
++ when(Whitelist.all()).thenReturn(new BlanketWhitelist());
+ }
+
+ private void usingNoListeners() {
+diff --git a/src/test/java/hudson/matrix/CombinationTest.java b/src/test/java/hudson/matrix/CombinationTest.java
+index 9ee7c60..d2fb555 100644
+--- a/src/test/java/hudson/matrix/CombinationTest.java
++++ b/src/test/java/hudson/matrix/CombinationTest.java
+@@ -23,15 +23,15 @@
+ */
+ package hudson.matrix;
+
+-import junit.framework.TestCase;
+-
+ import java.util.Map;
+ import java.util.HashMap;
+
++import org.jvnet.hudson.test.HudsonTestCase;
++
+ /**
+ * @author Kohsuke Kawaguchi
+ */
+-public class CombinationTest extends TestCase {
++public class CombinationTest extends HudsonTestCase {
+ AxisList axes = new AxisList(
+ new Axis("a","X","x"),
+ new Axis("b","Y","y"));
+diff --git a/src/test/java/hudson/matrix/MatrixTest.java b/src/test/java/hudson/matrix/MatrixTest.java
+index 369898c..c26bf5a 100644
+--- a/src/test/java/hudson/matrix/MatrixTest.java
++++ b/src/test/java/hudson/matrix/MatrixTest.java
+@@ -23,12 +23,21 @@
+ */
+ package hudson.matrix;
+
++import hudson.Functions;
+ import hudson.model.Item;
+ import hudson.security.AuthorizationMatrixProperty;
+ import hudson.security.ProjectMatrixAuthorizationStrategy;
++
++import java.io.IOException;
+ import java.util.Collections;
++import java.util.Set;
++
+ import org.acegisecurity.context.SecurityContextHolder;
++
+ import com.gargoylesoftware.htmlunit.xml.XmlPage;
++
++import org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException;
++import org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval;
+ import org.jvnet.hudson.test.HudsonTestCase;
+ import org.jvnet.hudson.test.Bug;
+
+@@ -73,4 +82,32 @@ public class MatrixTest extends HudsonTestCase {
+ XmlPage xml = new WebClient().goToXml(project.getUrl() + "api/xml");
+ assertEquals(4, xml.getByXPath("//matrixProject/activeConfiguration").size());
+ }
++
++ // @Issue("SECURITY-125")
++ public void testCombinationFilterSecurity() throws Exception {
++ MatrixProject project = createMatrixProject();
++ String combinationFilter = "jenkins.model.Jenkins.getInstance().setSystemMessage('hacked')";
++ expectRejection(project, combinationFilter, "staticMethod jenkins.model.Jenkins getInstance");
++ assertNull(jenkins.getSystemMessage());
++ expectRejection(project, combinationFilter, "method jenkins.model.Jenkins setSystemMessage java.lang.String");
++ assertNull(jenkins.getSystemMessage());
++ project.setCombinationFilter(combinationFilter);
++ assertEquals("you asked for it", "hacked", jenkins.getSystemMessage());
++ }
++
++ private static void expectRejection(MatrixProject project, String combinationFilter, String signature)
++ throws IOException {
++ ScriptApproval scriptApproval = ScriptApproval.get();
++ assertEquals(Collections.emptySet(), scriptApproval.getPendingSignatures());
++ try {
++ project.setCombinationFilter(combinationFilter);
++ } catch (RejectedAccessException x) {
++ assertEquals(Functions.printThrowable(x), signature, x.getSignature());
++ }
++ Set<ScriptApproval.PendingSignature> pendingSignatures = scriptApproval.getPendingSignatures();
++ assertEquals(1, pendingSignatures.size());
++ assertEquals(signature, pendingSignatures.iterator().next().signature);
++ scriptApproval.approveSignature(signature);
++ assertEquals(Collections.emptySet(), scriptApproval.getPendingSignatures());
++ }
+ }
+--
+2.1.0
+
diff --git a/jenkins-matrix-project-plugin.spec b/jenkins-matrix-project-plugin.spec
index 922e2fc..09b1328 100644
--- a/jenkins-matrix-project-plugin.spec
+++ b/jenkins-matrix-project-plugin.spec
@@ -4,7 +4,7 @@
Name: jenkins-%{mod_name}
Version: 1.4
-Release: 1%{?dist}
+Release: 2%{?dist}
Summary: Jenkins Matrix Project Plugin
# License is specified in pom.xml
@@ -14,6 +14,8 @@ Source0: https://github.com/jenkinsci/%{mod_name}/archive/%{short_name}-%
# Text copied from http://www.opensource.org/licenses/mit-license.php
Source1: LICENSE.txt
+Patch0: 0001-Fix-SECURITY-125.patch
+
BuildRequires: maven-local
BuildRequires: mvn(org.jenkins-ci.plugins:plugin:pom:)
BuildRequires: mvn(org.kohsuke:access-modifier-checker)
@@ -36,6 +38,8 @@ This package contains the API documentation for %{name}.
%prep
%setup -q -n %{mod_name}-%{short_name}-%{version}
+%patch0 -p1
+
cp %{SOURCE1} .
%mvn_package ::hpi: __noinstall
%mvn_file ::jar:: %{name}/%{short_name} %{plugin_home}/WEB-INF/lib/%{short_name}
@@ -67,6 +71,10 @@ sed -i 's|%{plugin_home}/WEB-INF/lib/%{short_name}.jar||' .mfiles
%doc LICENSE.txt
%changelog
+* Sun Mar 29 2015 Michal Srb <msrb at redhat.com> - 1.4-2
+- Fix SECURITY-125
+- Resolves: CVE-2015-1806
+
* Fri Nov 21 2014 Michal Srb <msrb at redhat.com> - 1.4-1
- Update to upstream version 1.4
--
cgit v0.10.2
http://pkgs.fedoraproject.org/cgit/jenkins-matrix-project-plugin.git/commit/?h=f21&id=7c978515519cbaf49b7c26b65f48bfe7be97d6bd
More information about the scm-commits
mailing list