Skip to content

Commit 882a7d3

Browse files
committed
[SECURITY-2075] [SECURITY-2076] [SECURITY-2698]
1 parent eeae3e7 commit 882a7d3

File tree

12 files changed

+42
-8
lines changed

12 files changed

+42
-8
lines changed

src/main/java/hudson/scm/SubversionSCM.java

+5
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@
168168
import org.kohsuke.stapler.StaplerResponse;
169169
import org.kohsuke.stapler.export.Exported;
170170
import org.kohsuke.stapler.export.ExportedBean;
171+
import org.kohsuke.stapler.verb.POST;
171172
import org.tmatesoft.svn.core.*;
172173
import org.tmatesoft.svn.core.auth.*;
173174
import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory;
@@ -2279,6 +2280,7 @@ public ISVNAuthenticationProvider createAuthenticationProvider() {
22792280
* Submits the authentication info.
22802281
*/
22812282
// TODO: stapler should do multipart/form-data handling
2283+
@POST
22822284
public void doPostCredential(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
22832285
Jenkins.getInstance().checkPermission(Item.CONFIGURE);
22842286

@@ -2345,6 +2347,7 @@ public void postCredential(String url, final UserProvidedCredential upc, PrintWr
23452347
*/
23462348
@CheckForNull
23472349
@Deprecated
2350+
@RequirePOST
23482351
public FormValidation doCheckRemote(StaplerRequest req, @AncestorInPath AbstractProject context, @QueryParameter String value, @QueryParameter String credentialsId) {
23492352
Jenkins instance = Jenkins.getInstance();
23502353
if (instance != null) {
@@ -2528,6 +2531,7 @@ public FormValidation doCheckExcludedCommitMessages(@QueryParameter String value
25282531
/**
25292532
* Validates the remote server supports custom revision properties
25302533
*/
2534+
@RequirePOST
25312535
public FormValidation doCheckRevisionPropertiesSupported(@AncestorInPath Item context,
25322536
@QueryParameter String value,
25332537
@QueryParameter String credentialsId,
@@ -3191,6 +3195,7 @@ public ListBoxModel fillCredentialsIdItems(@CheckForNull Item context, String re
31913195
/**
31923196
* Validate the value for a remote (repository) location.
31933197
*/
3198+
@RequirePOST
31943199
public FormValidation doCheckRemote(/* TODO unused, delete */StaplerRequest req, @AncestorInPath Item context,
31953200
@QueryParameter String remote) {
31963201

src/main/java/hudson/scm/SubversionTagAction.java

+2
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
import org.kohsuke.stapler.StaplerResponse;
5656
import org.kohsuke.stapler.export.Exported;
5757
import org.kohsuke.stapler.export.ExportedBean;
58+
import org.kohsuke.stapler.verb.POST;
5859
import org.tmatesoft.svn.core.SVNException;
5960
import org.tmatesoft.svn.core.SVNURL;
6061
import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
@@ -212,6 +213,7 @@ public String makeTagURL(SvnInfo si) {
212213
/**
213214
* Invoked to actually tag the workspace.
214215
*/
216+
@POST
215217
public synchronized void doSubmit(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
216218
getACL().checkPermission(getPermission());
217219

src/main/java/hudson/scm/browsers/FishEyeSVN.java

+2
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import java.net.MalformedURLException;
4242
import java.net.URL;
4343
import java.util.regex.Pattern;
44+
import org.kohsuke.stapler.interceptor.RequirePOST;
4445

4546
/**
4647
* {@link RepositoryBrowser} for FishEye SVN.
@@ -130,6 +131,7 @@ public String getDisplayName() {
130131
/**
131132
* Performs on-the-fly validation of the URL.
132133
*/
134+
@RequirePOST
133135
public FormValidation doCheckUrl(@QueryParameter(fixEmpty=true) String value) throws IOException, ServletException {
134136
if(value==null) // nothing entered yet
135137
return FormValidation.ok();

src/main/java/hudson/scm/browsers/Sventon.java

+2
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import java.net.URL;
4343
import java.net.URLEncoder;
4444
import jenkins.model.Jenkins;
45+
import org.kohsuke.stapler.interceptor.RequirePOST;
4546

4647
/**
4748
* {@link RepositoryBrowser} for Sventon 1.x.
@@ -97,6 +98,7 @@ public String getDisplayName() {
9798
/**
9899
* Performs on-the-fly validation of the URL.
99100
*/
101+
@RequirePOST
100102
public FormValidation doCheckUrl(@AncestorInPath Item project,
101103
@QueryParameter(fixEmpty=true) final String value)
102104
throws IOException, ServletException {

src/main/java/hudson/scm/browsers/Sventon2.java

+2
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import java.net.URL;
4444
import java.net.URLEncoder;
4545
import jenkins.model.Jenkins;
46+
import org.kohsuke.stapler.interceptor.RequirePOST;
4647

4748
/**
4849
* {@link RepositoryBrowser} for Sventon 2.x.
@@ -117,6 +118,7 @@ public String getDisplayName() {
117118
/**
118119
* Performs on-the-fly validation of the URL.
119120
*/
121+
@RequirePOST
120122
public FormValidation doCheckUrl(@AncestorInPath Item project,
121123
@QueryParameter(fixEmpty=true) final String value)
122124
throws IOException, ServletException {

src/main/java/hudson/scm/listtagsparameter/ListSubversionTagsParameterDefinition.java

+1
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,7 @@ public ISVNAuthenticationProvider createAuthenticationProvider(AbstractProject c
378378
}
379379

380380
@CheckForNull
381+
@RequirePOST
381382
public FormValidation doCheckTagsDir(StaplerRequest req, @AncestorInPath Item context, @QueryParameter String value) {
382383
Jenkins instance = Jenkins.getInstance();
383384
if (instance != null) {

src/main/resources/hudson/scm/SubversionSCM/ModuleLocation/config.jelly

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ THE SOFTWARE.
2525
<?jelly escape-by-default='true'?>
2626
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:c="/lib/credentials">
2727
<f:entry title="${%Repository URL}" field="remote" help="/scm/SubversionSCM/url-help">
28-
<f:textbox id="svn.remote.loc" onchange="{ /* workaround for JENKINS-19124 */
28+
<f:textbox checkMethod="post" id="svn.remote.loc" onchange="{ /* workaround for JENKINS-19124 */
2929
var self=this.targetElement ? this.targetElement : this;
3030
var r=findNextFormItem(self,'credentialsId');
3131
r.onchange(r);

src/main/resources/hudson/scm/SubversionSCM/config.jelly

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ THE SOFTWARE.
5757
<f:textarea />
5858
</f:entry>
5959
<f:entry title="${%Exclusion revprop name}" field="excludedRevprop">
60-
<f:textbox checkUrl="'descriptorByName/hudson.scm.SubversionSCM/checkRevisionPropertiesSupported?value='+toValue(document.getElementById('svn.remote.loc'))+'&amp;credentialsId='+toValue(document.getElementById('svn.remote.cred'))+'&amp;excludedRevprop='+toValue(this)"/>
60+
<f:textbox checkMethod="post" checkUrl="'descriptorByName/hudson.scm.SubversionSCM/checkRevisionPropertiesSupported?value='+toValue(document.getElementById('svn.remote.loc'))+'&amp;credentialsId='+toValue(document.getElementById('svn.remote.cred'))+'&amp;excludedRevprop='+toValue(this)"/>
6161
</f:entry>
6262
<f:entry title="${%Filter changelog}" field="filterChangelog">
6363
<f:checkbox />

src/main/resources/hudson/scm/browsers/AbstractSventon/config.jelly

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ THE SOFTWARE.
2525
<?jelly escape-by-default='true'?>
2626
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
2727
<f:entry title="${%URL}" field="url">
28-
<f:textbox />
28+
<f:textbox checkMethod="post" />
2929
</f:entry>
3030
<f:entry title="${%Repository Instance}" field="repositoryInstance">
3131
<f:textbox />

src/main/resources/hudson/scm/browsers/FishEyeSVN/config.jelly

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ THE SOFTWARE.
2525
<?jelly escape-by-default='true'?>
2626
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
2727
<f:entry title="${%URL}" field="url">
28-
<f:textbox />
28+
<f:textbox checkMethod="post" />
2929
</f:entry>
3030
<f:entry title="${%Root module}" field="rootModule">
3131
<f:textbox />

src/main/resources/hudson/scm/listtagsparameter/ListSubversionTagsParameterDefinition/index.jelly

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
<!-- this is the page fragment displayed when triggering a new build -->
2626
<?jelly escape-by-default='true'?>
2727
<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form" xmlns:st="jelly:stapler">
28-
<f:entry title="${it.name}" description="${it.description}">
28+
<j:set var="escapeEntryTitleAndDescription" value="false"/>
29+
<f:entry title="${h.escape(it.name)}" description="${it.formattedDescription}">
2930
<!-- this div is required because of ParametersDefinitionProperty.java#117 -->
3031
<div name="parameter">
3132
<st:adjunct includes="lib.form.select.select"/>

src/test/java/hudson/scm/SubversionSCMTest.java

+22-3
Original file line numberDiff line numberDiff line change
@@ -138,18 +138,37 @@ public void taggingPermission() throws Exception {
138138
} catch (ElementNotFoundException e) {
139139
}
140140

141-
// and that tagging would fail
141+
// and that tagging would fail due to CSRF protection
142142
try {
143143
wc.getPage(b,"tagBuild/submit?name0=test&Submit=Tag");
144-
fail("should have been denied");
144+
fail("should have failed");
145+
} catch (FailingHttpStatusCodeException e) {
146+
// not found, wrong HTTP verb
147+
assertEquals(e.getResponse().getStatusCode(),404);
148+
}
149+
150+
// Now try with POST and crumb
151+
try {
152+
wc.getPage(new WebRequest(wc.createCrumbedUrl(b.getUrl() + "tagBuild/submit?name0=test&Submit=Tag"), HttpMethod.POST));
145153
} catch (FailingHttpStatusCodeException e) {
146154
// make sure the request is denied
147155
assertEquals(e.getResponse().getStatusCode(),403);
148156
}
149157

150-
// now login as alice and make sure that the tagging would succeed
158+
// now login as alice
151159
wc = r.createWebClient();
152160
wc.login("alice","alice");
161+
162+
// a quick detour to confirm CSRF protection is effective
163+
try {
164+
wc.getPage(b,"tagBuild/submit?name0=test&Submit=Tag");
165+
fail("should have failed");
166+
} catch (FailingHttpStatusCodeException e) {
167+
// not found, wrong HTTP verb
168+
assertEquals(e.getResponse().getStatusCode(),404);
169+
}
170+
171+
// make sure that the tagging would succeed
153172
html = wc.getPage(b,"tagBuild/");
154173
HtmlForm form = html.getFormByName("tag");
155174
r.submit(form);

0 commit comments

Comments
 (0)