Child pages
  • Configuring Content Security Policy
Skip to end of metadata
Go to start of metadata

Jenkins 1.641 / Jenkins 1.625.3 introduce the Content-Security-Policy header to static files served by Jenkins (specifically DirectoryBrowserSupport). This header is set to a very restrictive default set of permissions to protect Jenkins users from malicious HTML/JS files in workspaces, /userContent, or archived artifacts.

Unfortunately, several popular, useful plugins are affected by this and lose part of their functionality unless the default rules are relaxed.

The Default Rule Set

The default rule is set to:

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

This rule set results in the following:

  • No JavaScript allowed at all
  • No plugins (object/embed) allowed
  • No inline CSS, or CSS from other sites allowed
  • No images from other sites allowed
  • No frames allowed
  • No web fonts allowed
  • No XHR/AJAX allowed
  • etc.

In detail:

  • sandbox limits a number of things of what the page can do, similar to the sandbox attribute set on iframes. For a full list of what is prohibited, see this site. This attribute is not widely supported.
  • default-src 'none' prohibits loading scripts, URLs for AJAX/XHR/WebSockets/EventSources, fonts, plugin objects, media, and frames from anywhere (images and styles would also be prohibited, but are allowed by more specific rules described below).
  • img-src 'self' allows loading images from other files served by Jenkins. Inline image definitions are prohibited.
  • style-src 'self' allows loading style sheets from other files served by Jenkins. Inline style sheets are prohibited.

See content-security-policy.com for a reference on this header and its possible values.

Relaxing The Rules

Considerations

It depends on the specific Jenkins setup whether relaxing these rules substantially is safe.

The following needs to be taken into consideration:

  • Are less trusted users allowed to create or modify files in Jenkins workspaces? Jenkins builds pull requests sent by untrusted users, or employ a security model that limits trust in users allowed to configure one or more jobs, this also affects in what way the CSP rule set should be relaxed: Anything allowed there could be abused by users with the ability to change files in workspaces or archived artifacts.
  • Are some slaves not fully trusted? Even when Slave To Master Access Control is used to limit what slaves can do on the master node, the entire build directory on the master node is writable by slaves, with the exception of the build.xml file itself. Therefore any file stored in a build directory and served by Jenkins should be considered potentially unsafe.

If either of these are true, you should be very careful when relaxing the CSP rule set. If neither is true, and all users with the ability to change files in workspaces are fully trusted, as are all slave machines, then it should be safe to relax or even disable the CSP rules.

Implementation

The CSP header sent by Jenkins can be modified by setting the system property hudson.model.DirectoryBrowserSupport.CSP:

If its value is the empty string, e.g. java -Dhudson.model.DirectoryBrowserSupport.CSP= -jar jenkins.war then the header will not be sent at all.

This is potentially very unsafe and should only be used after reviewing the overall security setup.

Any other value will be used as the header value, e.g. java -Dhudson.model.DirectoryBrowserSupport.CSP="sandbox; default-src 'self';" -jar jenkins.war. See content-security-policy.com for a reference on this header and its possible values.

Changes to the system property will be effective immediately, so it's possible to set this system property temporarily via the Jenkins Script Console, allowing you to experiment with different values:

Set a custom value for the header:

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

Unset the header:

System.setProperty("hudson.model.DirectoryBrowserSupport.CSP", "")

Set the header to the default:

System.clearProperty("hudson.model.DirectoryBrowserSupport.CSP")

Find out the current header value:

System.getProperty("hudson.model.DirectoryBrowserSupport.CSP")

How to interpret the output:

  • No output below "Result" header: default protection
  • Output Result: below "Result" header: protection disabled
  • Output Result: some text here below "Result" header: custom protection

Forcing an uncached reload ("Shift-F5" or equivalent) of the affected web page may be necessary after changing the system property for the behavior to change.

Making Plugins Work

Maven Integration Plugin

Maven Integration Plugin has a feature that allows browsing generated Maven documentation sites (e.g. site:site) in Jenkins. When using this feature, it may be necessary to relax the CSP rule set to allow this to work. In limited testing, it was necessary to at least allow style-src 'unsafe-inline'. Depending on the site's content, more relaxed rules may be necessary.

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

Javadoc Plugin

The Javadoc Plugin makes Javadoc available for browsing in Jenkins. The default rule set does not allow use of frames in pages served by Jenkins. To make this work again, the directives frame-src 'self' and child-src 'self' must be added to the CSP header. It appears Safari also requires the sandbox directive to be removed.

default-src 'none'; img-src 'self'; style-src 'self'; child-src 'self'; frame-src 'self';

To see the ALL CLASSES link when browsing Javadoc without frames, script-src 'unsafe-inline' must also be added to the CSP header.

HTML Publisher Plugin

Make sure to update HTML Publisher Plugin to version 1.10 to make it work with Content Security Policy

From version 1.10 on, the HTML Publisher Plugin is compatible with Content Security Policy. Before that, it executed inline JavaScript in a file served by DirectoryBrowserSupport to set up the frame wrapper around the published files and would fail unless script-src 'unsafe-inline' was allowed, which is a possible security issue.

If the published HTML files require JavaScript or other dynamic features prohibited by Content Security Policy to work properly, the Content-Security-Policy header will need to be adjusted accordingly. This applies to all versions of HTML Publisher Plugin.

  • No labels

14 Comments

  1. The Gatling Plugin is also affected by this change.  I have documented the issue in Jira: https://issues.jenkins-ci.org/browse/JENKINS-32038

  2. OWASP Dependency Check Plugin's html reports are affected by this change, see https://issues.jenkins-ci.org/browse/JENKINS-32277

  3. As it is quite somehow very difficult to specify a Java system property with spaces, if you running inside Tomcat, I would recommand going through the catalina.properties files with is located under conf

  4. IMHO, it would be great to be able to specify this setting on a per-directory basis (unless I'm missing something and there is a way to do this?).

    Another plugin it breaks is the PHP Code Coverage report generated by PHPUnit which relies on Bootstrap.

      Google Chrome actually displays the styles, but won't load the fonts / bootstrap JS

      Safari doesn't even load the styles (due to the sandbox).

    Now we seem to be faced with:

       1) just disabling this thing site-wide (and re-exposing all the site-wide security issues that Jenkins has without it).

       2) Running apache in Parallel just to serve up the so-called-insecure content (and loosing the benefit of jenkins security)

    Unless I'm missing something?

  5. On windows the recipe above did not work - the java arguments in are in jenkins.xml next to jenkins.exe. I tried the following:

    -Dhudson.model.DirectoryBrowserSupport.CSP=
    -Dhudson.model.DirectoryBrowserSupport.CSP=""
    

    but it had no effect. Changing it to

    -Dhudson.model.DirectoryBrowserSupport.CSP="default-src 'self'; script-src '*'; connect-src '*'; img-src '*'; style-src '*';"
    

    worked for me... :-)

    1. using "*" as src is probably not the best idea (imagine a plugin delivering HTML that loads JS from mother-knows-where that captures the data from your browser and sends somewhere ..). I managed to get working following:

       
      -Dhudson.model.DirectoryBrowserSupport.CSP="default-src 'self' [https://jenkins.our.company.com]" 
      

      I experimented with sandbox settings too (tried all possible combinations) but with no luck. Interesting part is that when using sandbox, browser refuses to load content unless specific sandbox permission is set BUT setting a permission on server has no effect and setting a permission in browser is refused. If someone manged to use sandbox, I'd like very much to see the example configuration.

  6. For me HTML publisher is only working with following rule when loading code coverage report (generated by simplecov-html):

    System.setProperty("hudson.model.DirectoryBrowserSupport.CSP", "sandbox allow-scripts;")

     

    1. Finally for HTML publisher using simplecov api to generate html, CSP used is : System.setProperty("hudson.model.DirectoryBrowserSupport.CSP", "sandbox allow-same-origin allow-scripts; default-src 'self'; script-src * 'unsafe-eval'; img-src *; style-src * 'unsafe-inline'; font-src *"); 

  7. I run into the issue of the inline CSS  of my HTML report (using HTML report plugin) not being executed despite having disabled the header completely.
    What am I missing?

  8. This worked for me with Rubycritic:

    System.setProperty("hudson.model.DirectoryBrowserSupport.CSP", "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; img-src 'self'; style-src 'self' 'unsafe-inline'; font-src *");

  9. none of these are working for me I've even tried '*' in all of them yet still I get 403 forbidden on the images in the page. All of the images are local to the server as well.

    1. This works for me in Chrome with maven reports with frames → System.setProperty("hudson.model.DirectoryBrowserSupport.CSP", "default-src 'self'; img-src 'self' data: *; style-src 'self' 'unsafe-inline'; child-src 'self'; frame-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; frame-ancestors 'self'") The frame-ancestors gave me the breakthrough - The Chrome Developer tools is a good source of information.

  10. for me, on chrome 62.xxx  none of the solutions worked. Eventually, changing chrome settings for the Unsandboxed plugin for  jenkins page got it working. 

    How: On left of the url bar : 'i' icon → site settings → "Unsandboxed plug-in access" : set it to allow.

    chrome://settings/content/siteDetails?site=https://your_jenkins_domain.in


    However I'm still evaluating if there is any side effect (invitation to hack).


  11. I just want to mention that the info here does not cover for the case where you have some JavaScript (jQuery) that tries to load some data (jenkins artifact) inside an inframe, even if this is happening on the same domain.

    Chrome user may see `Refused to display '...' in a frame because it set 'X-Frame-Options' to 'sameorigin'.

    At this moment I don't know exactly what I need to configure on Jekins on nginx frontend in order to bypass this. Once I find I will update the comment, or maybe someone can share his workaround.