Skip to content

Commit 4b456b3

Browse files
committed
SECURITY-3559
1 parent 4a0914b commit 4b456b3

File tree

2 files changed

+25
-3
lines changed

2 files changed

+25
-3
lines changed

src/main/java/com/cloudbees/jenkins/plugins/advisor/BundleUpload.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.cloudbees.jenkins.plugins.advisor.client.model.Recipient;
88
import com.cloudbees.jenkins.support.SupportPlugin;
99
import hudson.Extension;
10+
import hudson.Util;
1011
import hudson.model.AsyncPeriodicWork;
1112
import hudson.model.TaskListener;
1213
import hudson.security.ACL;
@@ -102,11 +103,12 @@ private File generateBundle() {
102103
}
103104
} catch (Exception e) {
104105
logError(COULD_NOT_SAVE_SUPPORT_BUNDLE, e);
106+
var sanitizedMessage = Util.xmlEscape(e.getMessage());
105107
updateLastBundleResult(
106108
config,
107109
createTimestampedErrorMessage(
108110
"<strong>%s</strong><br/><pre><code>%s</code></pre>",
109-
COULD_NOT_SAVE_SUPPORT_BUNDLE, e.getMessage()));
111+
COULD_NOT_SAVE_SUPPORT_BUNDLE, sanitizedMessage));
110112
if (file != null && file.exists() && !file.delete()) {
111113
log(Level.WARNING, "Could not delete bundle {0}" + file);
112114
}
@@ -124,22 +126,24 @@ private void executeInternal(String email, File file, String pluginVersion) {
124126
if (response.getCode() == 200) {
125127
updateLastBundleResult(config, createTimestampedInfoMessage(BUNDLE_SUCCESSFULLY_UPLOADED));
126128
} else {
129+
var sanitizedMessage = Util.xmlEscape(response.getMessage());
127130
updateLastBundleResult(
128131
config,
129132
createTimestampedErrorMessage(
130133
"<strong>Bundle upload failed</strong><br/>Server response is: <code>%d - %s</code>",
131-
response.getCode(), response.getMessage()));
134+
response.getCode(), sanitizedMessage));
132135
}
133136
} catch (Exception e) {
134137
log(Level.SEVERE, "Issue while uploading file to bundle upload service: " + e.getMessage());
135138
log(
136139
Level.FINEST,
137140
"Exception while uploading file to bundle upload service. Cause: "
138141
+ ExceptionUtils.getStackTrace(e));
142+
var sanitizedMessage = Util.xmlEscape(e.getMessage());
139143
updateLastBundleResult(
140144
config,
141145
createTimestampedErrorMessage(
142-
"<strong>Bundle upload failed</strong><br/><pre><code>%s</code></pre>", e.getMessage()));
146+
"<strong>Bundle upload failed</strong><br/><pre><code>%s</code></pre>", sanitizedMessage));
143147
} finally {
144148
if (!file.delete()) {
145149
log(Level.WARNING, "Could not delete bundle {0}" + file);

src/test/java/com/cloudbees/jenkins/plugins/advisor/BundleUploadTest.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,24 @@ void getInitialDelay() {
153153
is(equalTo(TimeUnit.MINUTES.toMillis(BundleUpload.INITIAL_DELAY_MINUTES))));
154154
}
155155

156+
@WithTimeout(30)
157+
@Test
158+
void protectsAgainstRogueServer(JenkinsRule j) {
159+
var config = AdvisorGlobalConfiguration.getInstance();
160+
config.setEmail(TEST_EMAIL);
161+
config.setAcceptToS(true);
162+
163+
wireMock.stubFor(get(urlEqualTo("/api/health")).willReturn(aResponse().withStatus(200)));
164+
wireMock.stubFor(post(format(
165+
"/api/users/%s/upload/%s", TEST_EMAIL, j.getInstance().getLegacyInstanceId()))
166+
.willReturn(aResponse().withStatus(201).withBody("<img/src/onerror=alert(1)>")));
167+
168+
runBundleUpload(j);
169+
170+
// The stored response is properly escaped
171+
assertThat(config.getLastBundleResult(), containsString("<code>201 - &lt;img/src/onerror=alert(1)&gt;</code>"));
172+
}
173+
156174
/**
157175
* Runs the {@link BundleUpload} task and waits for it to finish.
158176
*/

0 commit comments

Comments
 (0)