diff --git a/changelog.html b/changelog.html
index 8e738d63281f120325ae410ba4747160fb584a04..178863ca3f83c0056a94c80906d614a721b33f6a 100644
--- a/changelog.html
+++ b/changelog.html
@@ -72,7 +72,10 @@ Upcoming changes
+
-
Added a new set-build-parameter command that can update a build variable from within a build.
@@ -95,7 +98,6 @@ Upcoming changes
-
Updated bundled plugins.
-
-
@@ -108,6 +110,15 @@ Upcoming changes
-
Breadcrumb is reworked to show descendants to provide additional navigational shortcuts.
(discussion)
+
-
+ Fixed CSRF vulnerabilities
+ (SECURITY-63,SECURITY-69)
+
-
+ Fixed an XSS vulnerability via stylesheet
+ (SECURITY-67)
+
-
+ Fixed an XSS vulnerability to copy arbitrary text into clipboard
+ (SECURITY-71/CVE-2013-1808)
diff --git a/core/pom.xml b/core/pom.xml
index e2e0f91dff3eae792ed3fea943e29cb618497631..48028a7a9095a4015105b0dad2b62ddc272c8d97 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -164,7 +164,7 @@ THE SOFTWARE.
org.kohsuke.stapler
stapler-adjunct-zeroclipboard
- 1.0.7-2
+ 1.1.7-1
org.kohsuke.stapler
diff --git a/core/src/main/java/hudson/markup/MyspacePolicy.java b/core/src/main/java/hudson/markup/MyspacePolicy.java
index f0543f953811b12b44b74f62364cb6e45be7b1f3..46d0c31e2296544f0a8ea21dc7ea2bdb25bf359b 100644
--- a/core/src/main/java/hudson/markup/MyspacePolicy.java
+++ b/core/src/main/java/hudson/markup/MyspacePolicy.java
@@ -67,7 +67,6 @@ public class MyspacePolicy {
tag("img", "src",ONSITE_OR_OFFSITE_URL,
"hspace","vspace");
tag("iframe", "src");
- tag("link", "type","rel");
tag("ul,ol,li,dd,dl,dt,thead,tbody,tfoot");
tag("table", "noresize");
tag("td,th,tr");
diff --git a/core/src/main/java/hudson/model/Computer.java b/core/src/main/java/hudson/model/Computer.java
index cc0edeb367bd451392a39f150f1291f790474fc1..07787414357476a4f383486a7f0cd14e62d9e409 100644
--- a/core/src/main/java/hudson/model/Computer.java
+++ b/core/src/main/java/hudson/model/Computer.java
@@ -51,8 +51,6 @@ import hudson.slaves.RetentionStrategy;
import hudson.slaves.WorkspaceList;
import hudson.slaves.OfflineCause;
import hudson.slaves.OfflineCause.ByCLI;
-import hudson.tasks.BuildWrapper;
-import hudson.tasks.Publisher;
import hudson.util.DaemonThreadFactory;
import hudson.util.EditDistance;
import hudson.util.ExceptionCatchingThreadFactory;
@@ -1157,20 +1155,7 @@ public /*transient*/ abstract class Computer extends Actionable implements Acces
}
protected void _doScript( StaplerRequest req, StaplerResponse rsp, String view) throws IOException, ServletException {
- // ability to run arbitrary script is dangerous
- checkPermission(Jenkins.RUN_SCRIPTS);
-
- String text = req.getParameter("script");
- if(text!=null) {
- try {
- req.setAttribute("output",
- RemotingDiagnostics.executeGroovy(text,getChannel()));
- } catch (InterruptedException e) {
- throw new ServletException(e);
- }
- }
-
- req.getView(this,view).forward(req, rsp);
+ Jenkins._doScript(req, rsp, req.getView(this, view), getChannel(), getACL());
}
/**
diff --git a/core/src/main/java/jenkins/model/Jenkins.java b/core/src/main/java/jenkins/model/Jenkins.java
index 7ed3304bac603d53a1b25f9ea76ba8e573f156b2..b2efe0caa51aa2d8c287298f2d2e96f2712118f0 100755
--- a/core/src/main/java/jenkins/model/Jenkins.java
+++ b/core/src/main/java/jenkins/model/Jenkins.java
@@ -261,6 +261,7 @@ import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.BindException;
+import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;
import java.security.SecureRandom;
@@ -3357,25 +3358,31 @@ public class Jenkins extends AbstractCIBase implements ModifiableTopLevelItemGro
* Run arbitrary Groovy script.
*/
public void doScript(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
- doScript(req, rsp, req.getView(this, "_script.jelly"));
+ _doScript(req, rsp, req.getView(this, "_script.jelly"), MasterComputer.localChannel, getACL());
}
/**
* Run arbitrary Groovy script and return result as plain text.
*/
public void doScriptText(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
- doScript(req, rsp, req.getView(this, "_scriptText.jelly"));
+ _doScript(req, rsp, req.getView(this, "_scriptText.jelly"), MasterComputer.localChannel, getACL());
}
- private void doScript(StaplerRequest req, StaplerResponse rsp, RequestDispatcher view) throws IOException, ServletException {
+ /**
+ * @since 1.509.1
+ */
+ public static void _doScript(StaplerRequest req, StaplerResponse rsp, RequestDispatcher view, VirtualChannel channel, ACL acl) throws IOException, ServletException {
// ability to run arbitrary script is dangerous
- checkPermission(RUN_SCRIPTS);
+ acl.checkPermission(RUN_SCRIPTS);
String text = req.getParameter("script");
if (text != null) {
+ if (!"POST".equals(req.getMethod())) {
+ throw HttpResponses.error(HttpURLConnection.HTTP_BAD_METHOD, "requires POST");
+ }
try {
req.setAttribute("output",
- RemotingDiagnostics.executeGroovy(text, MasterComputer.localChannel));
+ RemotingDiagnostics.executeGroovy(text, channel));
} catch (InterruptedException e) {
throw new ServletException(e);
}
@@ -3391,7 +3398,7 @@ public class Jenkins extends AbstractCIBase implements ModifiableTopLevelItemGro
*/
@RequirePOST
public void doEval(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
- checkPermission(ADMINISTER);
+ checkPermission(RUN_SCRIPTS);
try {
MetaClass mc = WebApp.getCurrent().getMetaClass(getClass());
diff --git a/core/src/test/java/hudson/markup/MyspacePolicyTest.java b/core/src/test/java/hudson/markup/MyspacePolicyTest.java
index cb1a63e2bb9341a5ecc4fc1d0db1d2fa43ef9395..75ac37b28c3676fb4bce9a49c6795512d9bcb196 100644
--- a/core/src/test/java/hudson/markup/MyspacePolicyTest.java
+++ b/core/src/test/java/hudson/markup/MyspacePolicyTest.java
@@ -43,7 +43,7 @@ public class MyspacePolicyTest extends Assert {
assertReject("script","");
assertIntact("");
- assertIntact("");
+ assertReject("link", "");
assertIntact("inline CSS
");
assertIntact("
");
diff --git a/debian/debian/changelog b/debian/debian/changelog
index 4f730b9aa718c4d6f66baed7b70e5af63e6fca66..9db182f2e94844c1bce4f5ca1cc615bdc40d0b1c 100644
--- a/debian/debian/changelog
+++ b/debian/debian/changelog
@@ -1,3 +1,9 @@
+jenkins (1.514) unstable; urgency=low
+
+ * See http://jenkins-ci.org/changelog for more details.
+
+ -- Kohsuke Kawaguchi Wed, 01 May 2013 20:15:32 -0700
+
jenkins (1.513) unstable; urgency=low
* See http://jenkins-ci.org/changelog for more details.
diff --git a/maven-plugin/src/main/java/hudson/maven/MavenProbeAction.java b/maven-plugin/src/main/java/hudson/maven/MavenProbeAction.java
index dbf4acf2bbd73888e2bf30d5cb9ee15bf239d8de..5efe9ee56cb661e882afd6dbc4de497f6ed49985 100644
--- a/maven-plugin/src/main/java/hudson/maven/MavenProbeAction.java
+++ b/maven-plugin/src/main/java/hudson/maven/MavenProbeAction.java
@@ -97,21 +97,7 @@ public final class MavenProbeAction implements Action {
}
public void doScript( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException {
- // ability to run arbitrary script is dangerous,
- // so tie it to the admin access
- owner.checkPermission(Jenkins.RUN_SCRIPTS);
-
- String text = req.getParameter("script");
- if(text!=null) {
- try {
- req.setAttribute("output",
- RemotingDiagnostics.executeGroovy(text,channel));
- } catch (InterruptedException e) {
- throw new ServletException(e);
- }
- }
-
- req.getView(this,"_script.jelly").forward(req,rsp);
+ Jenkins._doScript(req, rsp, req.getView(this, "_script.jelly"), channel, owner.getACL());
}
/**
diff --git a/maven-plugin/src/main/java/hudson/maven/reporters/MavenAbstractArtifactRecord.java b/maven-plugin/src/main/java/hudson/maven/reporters/MavenAbstractArtifactRecord.java
index 482fc70c483d04692f73d66daed8395e0306d196..95681e5eb6ea5393cdc0757b8390142895d160da 100644
--- a/maven-plugin/src/main/java/hudson/maven/reporters/MavenAbstractArtifactRecord.java
+++ b/maven-plugin/src/main/java/hudson/maven/reporters/MavenAbstractArtifactRecord.java
@@ -65,6 +65,7 @@ import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.export.Exported;
import org.kohsuke.stapler.export.ExportedBean;
+import org.kohsuke.stapler.interceptor.RequirePOST;
/**
* UI to redeploy artifacts after the fact.
@@ -208,6 +209,7 @@ public abstract class MavenAbstractArtifactRecord>
/**
* Performs a redeployment.
*/
+ @RequirePOST
public final HttpResponse doRedeploy(
@QueryParameter("_.id") final String id,
@QueryParameter("_.url") final String repositoryUrl,
diff --git a/test/src/test/java/jenkins/model/JenkinsTest.java b/test/src/test/java/jenkins/model/JenkinsTest.java
index 46700d51957d1300f451ec7a4700f81045381188..250d9591f540731e20763ac4dbfb0c435a9213ec 100644
--- a/test/src/test/java/jenkins/model/JenkinsTest.java
+++ b/test/src/test/java/jenkins/model/JenkinsTest.java
@@ -23,6 +23,9 @@
*/
package jenkins.model;
+import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
+import com.gargoylesoftware.htmlunit.HttpMethod;
+import com.gargoylesoftware.htmlunit.WebRequestSettings;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import hudson.maven.MavenModuleSet;
import hudson.maven.MavenModuleSetBuild;
@@ -32,6 +35,9 @@ import hudson.security.FullControlOnceLoggedInAuthorizationStrategy;
import hudson.util.HttpResponses;
import junit.framework.Assert;
import hudson.model.FreeStyleProject;
+import hudson.security.GlobalMatrixAuthorizationStrategy;
+import hudson.security.LegacySecurityRealm;
+import hudson.security.Permission;
import hudson.util.FormValidation;
import org.junit.Test;
@@ -41,6 +47,7 @@ import org.jvnet.hudson.test.HudsonTestCase;
import org.jvnet.hudson.test.TestExtension;
import org.kohsuke.stapler.HttpResponse;
import java.net.HttpURLConnection;
+import java.net.URL;
/**
* @author kingfai
@@ -237,6 +244,75 @@ public class JenkinsTest extends HudsonTestCase {
assertEquals(3,jenkins.getExtensionList(RootAction.class).get(RootActionImpl.class).count);
}
+ public void testDoScript() throws Exception {
+ jenkins.setSecurityRealm(new LegacySecurityRealm());
+ GlobalMatrixAuthorizationStrategy gmas = new GlobalMatrixAuthorizationStrategy() {
+ @Override public boolean hasPermission(String sid, Permission p) {
+ return p == Jenkins.RUN_SCRIPTS ? hasExplicitPermission(sid, p) : super.hasPermission(sid, p);
+ }
+ };
+ gmas.add(Jenkins.ADMINISTER, "alice");
+ gmas.add(Jenkins.RUN_SCRIPTS, "alice");
+ gmas.add(Jenkins.READ, "bob");
+ gmas.add(Jenkins.ADMINISTER, "charlie");
+ jenkins.setAuthorizationStrategy(gmas);
+ WebClient wc = createWebClient();
+ wc.login("alice");
+ wc.goTo("script");
+ wc.assertFails("script?script=System.setProperty('hack','me')", HttpURLConnection.HTTP_BAD_METHOD);
+ assertNull(System.getProperty("hack"));
+ WebRequestSettings req = new WebRequestSettings(new URL(wc.getContextPath() + "script?script=System.setProperty('hack','me')"), HttpMethod.POST);
+ wc.getPage(wc.addCrumb(req));
+ assertEquals("me", System.getProperty("hack"));
+ wc.assertFails("scriptText?script=System.setProperty('hack','me')", HttpURLConnection.HTTP_BAD_METHOD);
+ req = new WebRequestSettings(new URL(wc.getContextPath() + "scriptText?script=System.setProperty('huck','you')"), HttpMethod.POST);
+ wc.getPage(wc.addCrumb(req));
+ assertEquals("you", System.getProperty("huck"));
+ wc.login("bob");
+ wc.assertFails("script", HttpURLConnection.HTTP_FORBIDDEN);
+ wc.login("charlie");
+ wc.assertFails("script", HttpURLConnection.HTTP_FORBIDDEN);
+ }
+
+ public void testDoEval() throws Exception {
+ jenkins.setSecurityRealm(new LegacySecurityRealm());
+ GlobalMatrixAuthorizationStrategy gmas = new GlobalMatrixAuthorizationStrategy() {
+ @Override public boolean hasPermission(String sid, Permission p) {
+ return p == Jenkins.RUN_SCRIPTS ? hasExplicitPermission(sid, p) : super.hasPermission(sid, p);
+ }
+ };
+ gmas.add(Jenkins.ADMINISTER, "alice");
+ gmas.add(Jenkins.RUN_SCRIPTS, "alice");
+ gmas.add(Jenkins.READ, "bob");
+ gmas.add(Jenkins.ADMINISTER, "charlie");
+ jenkins.setAuthorizationStrategy(gmas);
+ // Otherwise get "RuntimeException: Trying to set the request parameters, but the request body has already been specified;the two are mutually exclusive!" from WebRequestSettings.setRequestParameters when POSTing content:
+ jenkins.setCrumbIssuer(null);
+ WebClient wc = createWebClient();
+ wc.login("alice");
+ wc.assertFails("eval", HttpURLConnection.HTTP_INTERNAL_ERROR);
+ assertEquals("3", eval(wc));
+ wc.login("bob");
+ try {
+ eval(wc);
+ fail("bob has only READ");
+ } catch (FailingHttpStatusCodeException e) {
+ assertEquals(HttpURLConnection.HTTP_FORBIDDEN, e.getStatusCode());
+ }
+ wc.login("charlie");
+ try {
+ eval(wc);
+ fail("charlie has ADMINISTER but not RUN_SCRIPTS");
+ } catch (FailingHttpStatusCodeException e) {
+ assertEquals(HttpURLConnection.HTTP_FORBIDDEN, e.getStatusCode());
+ }
+ }
+ private String eval(WebClient wc) throws Exception {
+ WebRequestSettings req = new WebRequestSettings(new URL(wc.getContextPath() + "eval"), HttpMethod.POST);
+ req.setRequestBody("${1+2}");
+ return wc.getPage(/*wc.addCrumb(*/req/*)*/).getWebResponse().getContentAsString();
+ }
+
@TestExtension("testUnprotectedRootAction")
public static class RootActionImpl implements UnprotectedRootAction {
private int count;