提交 27c30341 编写于 作者: J Jesse Glick

Merge pull request #49 from jenkinsci-cert/SECURITY-95

[FIX SECURITY-95] Add CSP headers to files served by Jenkins
......@@ -47,6 +47,8 @@ import jenkins.util.VirtualFile;
import org.apache.commons.io.IOUtils;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipOutputStream;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.stapler.HttpResponse;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
......@@ -307,6 +309,17 @@ public final class DirectoryBrowserSupport implements HttpResponse {
// pseudo file name to let the Stapler set text/plain
rsp.serveFile(req, in, lastModified, -1, length, "plain.txt");
} else {
String csp = System.getProperty(DirectoryBrowserSupport.class.getName() + ".CSP");
if (csp == null) {
// default value unless overridden with system property
csp = DEFAULT_CSP_VALUE;
}
if (!csp.trim().equals("")) {
// allow users to prevent sending this header by setting empty system property
for (String header : new String[]{"Content-Security-Policy", "X-WebKit-CSP", "X-Content-Security-Policy"}) {
rsp.setHeader(header, csp);
}
}
rsp.serveFile(req, in, lastModified, -1, length, baseFile.getName() );
}
}
......@@ -574,4 +587,7 @@ public final class DirectoryBrowserSupport implements HttpResponse {
private static final Logger LOGGER = Logger.getLogger(DirectoryBrowserSupport.class.getName());
@Restricted(NoExternalUse.class)
public static final String DEFAULT_CSP_VALUE = "sandbox; default-src 'none'; img-src 'self'; style-src 'self';";
}
......@@ -169,6 +169,36 @@ public class DirectoryBrowserSupportTest {
zipfile.delete();
}
@Issue("SECURITY-95")
@Test
public void contentSecurityPolicy() throws Exception {
FreeStyleProject p = j.createFreeStyleProject();
p.setScm(new SingleFileSCM("test.html", "<html><body><h1>Hello world!</h1></body></html>"));
p.getPublishersList().add(new ArtifactArchiver("*", "", true));
assertEquals(Result.SUCCESS, p.scheduleBuild2(0).get().getResult());
HtmlPage page = j.createWebClient().goTo("job/" + p.getName() + "/lastSuccessfulBuild/artifact/test.html");
for (String header : new String[]{"Content-Security-Policy", "X-WebKit-CSP", "X-Content-Security-Policy"}) {
assertEquals("Header set: " + header, page.getWebResponse().getResponseHeaderValue(header), DirectoryBrowserSupport.DEFAULT_CSP_VALUE);
}
String propName = DirectoryBrowserSupport.class.getName() + ".CSP";
String initialValue = System.getProperty(propName);
try {
System.setProperty(propName, "");
page = j.createWebClient().goTo("job/" + p.getName() + "/lastSuccessfulBuild/artifact/test.html");
for (String header : new String[]{"Content-Security-Policy", "X-WebKit-CSP", "X-Content-Security-Policy"}) {
assertFalse("Header not set: " + header, page.getWebResponse().getResponseHeaders().contains(header));
}
} finally {
if (initialValue == null) {
System.clearProperty(DirectoryBrowserSupport.class.getName() + ".CSP");
} else {
System.setProperty(DirectoryBrowserSupport.class.getName() + ".CSP", initialValue);
}
}
}
private File download(UnexpectedPage page) throws IOException {
File file = File.createTempFile("DirectoryBrowserSupport", "zipDownload");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册