Managing the Content Security Policy on Jenkins

Many Jenkins plugins require changes to the default Content Security Policy (or CSP) to work correctly. A refresher on what CSP is and why you should care about it can be found HERE and HERE. If you use a hosted Jenkins installation, you’ll probably need to contact your service provider to do the necessary changes for you. However if you have a self-managed installation, please read on.

The first step is to come up with a set of CSP rules that work for you. The most secure practice is to allow as little content as possible, so strive for the strongest set of rules that allow your plugins to work correctly. Apart from the pages mentioned above, I’ve found THIS StackOverflow answer really helpful in finding the correct rules. Let’s say we came up with this:

sandbox; default-src 'none'; img-src 'self'; style-src 'self';

Next step if to apply this rule to your Jenkins. That’s done by setting the hudson.model.DirectoryBrowserSupport.CSP system property. There’s multiple ways of doing this, depending on how (and where) you’re using Jenkins:

1. Apply a new policy only temporary

Head over to the sub-URL /script of your Jenkins instance (e.g. something like http://localhost:8080/script). Alternatively open Jenkins -> Manage Jenkins -> Script Console. In the shell just execute:

System.setProperty("hudson.model.DirectoryBrowserSupport.CSP", "sandbox; default-src 'none'; img-src 'self'; style-src 'self';")

NOTE: The CSP will be reset to the default one next time Jenkins is restarted. This method is the easiest way to just test the effect of a new CSP policy to your Jenkins installation.

2. Starting Jenkins manually

In this case add an extra parameter to the command you’re using to start Jenkins:

java -Dhudson.model.DirectoryBrowserSupport.CSP="sandbox; default-src 'none'; img-src 'self'; style-src 'self';" -jar jenkins.war

The CSP parameter should be picked up by Jenkins and your new rules applied.

NOTE: The position of the parameter should be BEFORE the -jar jenkins.war command, or otherwise it won’t be picked up correctly and it won’t have any effect.

3. Jenkins on Windows machine

You probably have a service that automatically starts Jenkins when the machine is booted up. The configuration file for it is called jenkins.xml, located in the main Jenkins installation folder. Just add the new argument in the <arguments> element (and keep in mind the note about the order of arguments from above).

<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>-Dfile.encoding=UTF8 -Dhudson.lifecycle=hudson.lifecycle.WindowsServiceLifecycle -Dhudson.model.DirectoryBrowserSupport.CSP="sandbox; default-src 'none'; img-src 'self'; style-src 'self';" -jar "%BASE%\jenkins.war" --httpPort=<PORTNUM> --webroot="%BASE%\war"</arguments>
  <logmode>rotate</logmode>
  <onfailure action="restart" />
</service>

The changes will take effect after you restart the computer.

4. Jenkins on Mac installed via the official Jenkins installer

The installer has created a LaunchDaemon that starts Jenkins automatically when the machine is booted up. The actual command that’s executed is in this file:

/Library/Application\ Support/Jenkins/jenkins-runner.sh

At the bottom of the file you’ll see something like:

echo /usr/bin/java $javaArgs -jar "$war" $args
exec /usr/bin/java $javaArgs -jar "$war" $args

One option is to append the CSP parameter to the $javaArgs variable. However since the CSP parameter has a bunch of special characters in it, and the fact that’s a bash script, properly escaping all characters becomes quite painful. I ended up just appending the CSP parameter manually. Definitely not the most beautiful solution, but works great:

echo /usr/bin/java $javaArgs "-Dhudson.model.DirectoryBrowserSupport.CSP=sandbox; default-src 'none'; img-src 'self'; style-src 'self';" -jar "$war" $args
exec /usr/bin/java $javaArgs "-Dhudson.model.DirectoryBrowserSupport.CSP=sandbox; default-src 'none'; img-src 'self'; style-src 'self';" -jar "$war" $args

For the changes to take either restart the computer, or run the following commands:

sudo launchctl unload /Library/LaunchDaemons/org.jenkins-ci.plist
sudo launchctl load /Library/LaunchDaemons/org.jenkins-ci.plist

5. Jenkins on Mac installed via Homebrew

In this case the Jenkins service is managed by Homebrew, so the configuration file that needs editing is:

/usr/local/opt/jenkins/homebrew.mxcl.jenkins.plist

Just add the CSP parameter before the <string>-jar</string> line. Your config might look something like this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>homebrew.mxcl.jenkins</string>
    <key>ProgramArguments</key>
    <array>
      <string>/usr/libexec/java_home</string>
      <string>-v</string>
      <string>1.8</string>
      <string>--exec</string>
      <string>java</string>
      <string>-Dmail.smtp.starttls.enable=true</string>
      <string>-Dhudson.model.DirectoryBrowserSupport.CSP=sandbox; default-src 'self';</string>
      <string>-jar</string>
      <string>/usr/local/opt/jenkins/libexec/jenkins.war</string>
      <string>--httpListenAddress=127.0.0.1</string>
      <string>--httpPort=8080</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
  </dict>
</plist>

For the change to take effect either restart your computer or run the following commands:

brew services stop jenkins
brew services start jenkins

Hope this helps!

1 Comment

  1. Xavao curtiu! Valeu!

    Reply

Submit a Comment

Your email address will not be published. Required fields are marked *