One of the security features of Jenkins is to send Content Security Policy (CSP) headers which describes how certain resources can behave. The default policy blocks pretty much everything - no JavaScript, inline CSS, or even CSS from external websites. This can cause problems with content added to Jenkins via build processes, typically using the HTML Publisher Plugin.

While turning this policy off completely is not recommended it can be beneficial to adjust the policy to be less restrictive, allowing the user of external reports without compromising security.

Although I described modifying the CSP in an earlier post, I didn't realise at the time of publishing that the method I mentioned was only temporarily, and as soon as Jenkins was restarted, the defaults were reapplied. This post both covers that original method, and how to do it permanently, serving as a stand-alone reference.

The hudson.model.DirectoryBrowserSupport.CSP setting

The contents of the CSP headers are defined by the hudson.model.DirectoryBrowserSupport.CSP setting and supports a wide range of values - the CSP specification is very flexible and allows you to control how pretty much any type of resource is loaded, or what JavaScript features are permitted.

The specific configuration values are beyond the scope of this post, but you can learn more about CSP settings at a reference site.

In my own Jenkins instance, in order to get published NDepend analysis reports working, I ended up using the following policy which may be a good starting point for similar reports - it allows the use of JavaScript and line CSS, but leaves everything else blocked unless referenced directly from the Jenkins origin.

text
sandbox allow-scripts; default-src 'self'; style-src 'self' 'unsafe-inline';

Temporarily reconfiguring the Content Security Policy

To change the CSP, open the Script Console in Jenkins administration section, and run the following command

groovy
System.setProperty("hudson.model.DirectoryBrowserSupport.CSP", "sandbox allow-scripts; default-src 'self'; style-src 'self' 'unsafe-inline';")

Important! Changing the policy via the Script Console is not permanent and will revert back to the default values when Jenkins is restarted.

Permanently changing the Content Security Policy when running Jenkins via the command line

If you run Jenkins via the command line, e.g. by calling java.exe, you can add an extra argument to set the value of the CSP setting.

The Java documentation states you can use the -D argument to set a "system property value", allowing us to add the following to the command line

text
-Dhudson.model.DirectoryBrowserSupport.CSP="sandbox allow-scripts; default-src 'self'; style-src 'self' 'unsafe-inline';"

Remember to add double quotes around the CSP value, otherwise it will not be parsed correctly

A note on order of arguments

There's one important caveat though - the ordering of the parameters is important. I run Jenkins as a Windows service (more on that in the next section) and the command line I use looks similar to the following

text
-Xrs -Xmx256m -Dfile.encoding=UTF8 -Dhudson.lifecycle=hudson.lifecycle.WindowsServiceLifecycle -jar "%BASE%\jenkins.war" --httpPort=<PORTNUM> --webroot="%BASE%\war"

Initially I added the new argument to the end of that string, but this never had any effect - each time Jenkins started the value was missing. When checking the System Information view I noted the parameter wasn't listed in the main System Properties table but was instead appended to the value of another property - sun.java.command. That was the point I realized ordering mattered and moved the argument to before the --http argument. After that, the property setting was correctly applied.

Permanently changing the Content Security Policy when Jenkins is running as a Windows Service

If you run Jenkins as a Windows Service, the command parameters are read from jenkins.xml, which is located in your main Jenkins installation. If you open this file in the text editor of your choice, you should see XML similar to the following

xml
<service>
  <id>jenkins</id>
  <name>Jenkins</name>
  <description>This service runs Jenkins continuous integration system.</description>
  <env name="JENKINS_HOME" value="%BASE%"/>
  <executable>%BASE%\jre\bin\java</executable>
  <arguments>-Xrs -Xmx256m -Dfile.encoding=UTF8 -Dhudson.lifecycle=hudson.lifecycle.WindowsServiceLifecycle -jar "%BASE%\jenkins.war" --httpPort=<PORTNUM> --webroot="%BASE%\war"</arguments>
  <logmode>rotate</logmode>
  <onfailure action="restart" />
</service>

Simply add your new argument to the arguments element (with the same caveat that parameter ordering is important), save the file and restart Jenkins.

Note: The contents of the arguments element must be a single line, if line breaks are present the service will terminate on startup

Checking the value of the Content Security Policy setting

An easy way to check the CSP policy (regardless of if you set it via the command line or the Script Console) is to use Jenkins' System Information view. This view includes a System Properties table, if a custom CSP is in use, this will be displayed in the table.

Verifying that the CSP settings have been correctly recognised by Jenkins
Verifying that the CSP settings have been correctly recognised by Jenkins

Update History

  • 2017-02-03 - First published
  • 2020-11-21 - Updated formatting

Like what you're reading? Perhaps you like to buy us a coffee?

Donate via Buy Me a Coffee

Donate via PayPal


Comments