By default, our app adheres to the same HTTP headers (and respective protections) that the Atlassian application itself uses. By itself there is no need to do anything, if you are happy with what Atlassian does out of the box.

However we see some customers going beyond that & deploying the Atlassian applications behind application firewalls, reverse proxies etc. Some of these customers go as far as adding additional headers and measures that go beyond the default.

This article discusses these measures and the compatibility of our app with those.

Generally, there are several types of attacks on web applications and their users. While they always require an error or an oversight to exist in the web application, there are a couple of ways such problems can be mitigated should they occur. One of them is the use of several HTTP security headers in conjunction with a modern web browser that understands these. 

To mitigate any unknown attacks of certain types such as Cross-Site Scripting (XSS), Clickjacking or Cross-Frame Scripting (XFS), we recommend adding a couple of HTTP headers to responses sent from the Atlassian applications.

This document tries to give you some pointers on how to implement these hardening measures on your own system, but it does not claim to be a comprehensive guide. Always test these settings is a non-production environment since your situation may vary and these settings might not work in your case if, for example, some other apps require some changes to these policies. 


    Existing security headers

    Atlassian applications in current versions already send a couple of security headers, but these are on the conservative side and might be improved upon for our app. These headers are:

    Header nameHeader value
    Content-Security-Policy

    frame-ancestors 'self';

    X-Content-Type-Optionsnosniff
    X-Frame-Optionssameorigin
    X-XSS-Protection1; mode=block

    While the X-Content-Type-Options, X-Frame-Options and X-XSS-Protection headers are usually sufficient, there are additional headers that can be set and the Content-Security-Policy can be tightened. 

    Note that on Confluence, these headers are not sent automatically for apps. We have opened a bug report with Atlassian to investigate that: https://jira.atlassian.com/browse/CONFSERVER-57471 . Feel free to leave a vote. On Bitbucket, only the X-XSS-Protection header is sent. To fix these issues, just have your reverse proxy or load balancer send these headers.


    Improving upon the existing headers

    For our app's pages (reachable via "/plugins/servlet/samlsso"), the content security policy can be restricted even further and new headers can be introduced.

    Recommended additional header configuration

    Header nameHeader value
    Content-Security-Policy

    default-src 'self' 'unsafe-inline' 'unsafe-eval'; frame-ancestors 'self'; img-src 'self' data: https://www.gravatar.com;

    Feature-Policycamera 'none'; fullscreen 'none'; geolocation 'none'; microphone 'none'; payment 'none'; speaker 'none'; usb 'none'; vibrate 'none'; vr 'none';
    Referrer-Policystrict-origin
    Strict-Transport-Securitystrict-transport-security: max-age=31536000

    Content-Security-Policy

    The content security policy defines which sources may be used for which parts of the pages. In our case, we require 'self', 'unsafe-inline' and 'unsafe-eval' due to Atlassian's Javascript and CSS. For the image-src, we explicitly allow gravatar.com, since some applications allow using it for user avatars.

    Note that for testing the Content-Security-Policy on your system, you can give a report-uri and use the Content-Security-Policy-Report-Only header instead of Content-Security-Policy as detailed on MDN. We also found this blog article by a Dropbox engineer on testing CSPs and handling reports helpful. You may also want to use a service like report-uri.com to help debug your CSP.

    Also note that the frame-ancestors might have to be modified. For more details, see On using the host application in an iframe.

    Feature-Policy

    As another mitigation technique, you can explicitly disallow some features in case an attacker is able to inject code. The prepared statement should disallow most functions that can be used to spy on users (microphone, camera, geolocation) or trick them into doing something (payment, usb, fullscreen, vr). If you, for some reason, do require one of your SAML SSO page templates to use one of these functionalities, such as maybe geolocation-based IdP selection, you'll have to modify this header.

    Referrer-Policy

    This is a privacy feature. The referrer (or 'referer') header is sent to a server when you visit a website and were previously on another website. The target site can use that header to see where you came from. The value we chose strict-origin will cause the referrer header to not be sent when a user visits a site on a different server. Disabling it should not cause any harm, but it can also not be completely ruled out that some IdPs don't require it. It may also mess with analytics a bit, but that should be uncritical in this use case.

    Strict-Transport-Security

    Use this with caution! If this header is delivered to a browser via an HTTPS connection, this browser will now always visit this website only via HTTPS and never via HTTP any more. Use this header only if absolutely know that your application will never have to be accessed via HTTP via that address. Note that you can still access it via HTTP via another address if needed. 


    On using the host application in an iframe 

    If the application is embedded in another website via frame or iframe, then the Content-Security-Policy and X-Frame-Options must be modified. Typical scenarios include:

    • Running the application in an intranet portal
    • Using Jira Service Desk issue collectors
    • Using Confluence as a knowledge base in Jira Service Desk

    If any of these cases apply and you're having trouble embedding the application, then you might have to modify the aforementioned frame-related headers. Check your browser console errors regarding embedding to determine the cause for the issues.

    For example, if you want to embed the application on https://intranet.example.com, then you need to modify the following headers:

    Header nameHeader value
    Content-Security-Policy

    frame-ancestors 'self' https://intranet.example.com;

    X-Frame-Optionsallow-from https://intranet.example.com

    For more informations on this, check Atlassian's documentation.


    How to set HTTP security headers

    These headers are usually set by either the host application or a reverse proxy / load balancer. Here are some instructions on how to set the headers in a couple of popular reverse proxies / load balancers. If yours isn't in the list, consult your software's or service's documentation on how to achieve this.

    NGINX

    For each header you want to overwrite, add the following statements, adapted to the headers you want to set, to the appropriate server block:

    location /plugins/servlet/samlsso {
        add_header "Content-Security-Policy" "default-src 'self' 'unsafe-inline' 'unsafe-eval'; frame-ancestors 'self'; img-src 'self' data: https://www.gravatar.com;";
        add_header "Feature-Policy" "camera 'none'; fullscreen 'none'; geolocation 'none'; microphone 'none'; payment 'none'; speaker 'none'; usb 'none'; vibrate 'none'; vr 'none';";
        add_header "Referrer-Policy" "strict-origin";
    }

    For more information, check out the NGINX documentation for add_header.

    Note that this configuration may leave you with multiple versions of the headers, for example the CSP header. You can have nginx replace the existing headers by using the ngx_headers_more module and its more_set_headers directive.

    Apache httpd

    Make sure mod_headers is enabled. Then add the following statements, adapted to the headers you want to set, to the appropriate Proxy block in the appropriate Virtual Host config: 

    <Proxy "http://your-backend/plugins/servlet/samlsso">
        Header set "Content-Security-Policy" "default-src 'self' 'unsafe-inline' 'unsafe-eval'; frame-ancestors 'self'; img-src 'self' data: https://www.gravatar.com;"
        Header set "Feature-Policy" "camera 'none'; fullscreen 'none'; geolocation 'none'; microphone 'none'; payment 'none'; speaker 'none'; usb 'none'; vibrate 'none'; vr 'none';"
        Header set "Referrer-Policy" "strict-origin"
    </Proxy> 

    For more information, check out the Apache httpd documentation for Header set.

    Microsoft IIS

    You can use the HTTP Response Headers GUI in IIS Manager or add the following to your web.config:

    <system.webServer>
      <httpProtocol> <customHeaders> <add name="Content-Security-Policy" value="..." /> </customHeaders>
      </httpProtocol>
    </system.webServer>

    For more information, check out the Microsoft IIS documentation for customHeaders.


    Further steps & information

    Here are a couple of links from which we drew information while compiling this document: