Search code examples
javascriptwebhttp-headersfetchcontent-security-policy

Understanding connect-src, script-src and style-src when everything is loaded dynamically


I am a little confused with the directives available with Content Security Policy Header. Mainly confused with connect-src , script-src and style-src

I have a javascript, which sends Fetch, Ajax (on the same domain) and dynamically loads a link tag that has a stylesheet.

If I have to get my script whitelisted on a domain, should this be part of all connect-src, script-src and style-src ? I am a little confused here.

To make it clearer, there is a script at https://example.com which loads, sends data from https://example.com and loads stylesheet sitting at https://some-another-domain.com. How should the content security policy reflect this? Should connect-src , script-src and style-src include both the domains?

Could someone help clarify this?


Solution

  • Each directive should contain only sources which it covers (controls).

    1. The connect-src directive covers the URLs from which resources can be loaded using following script API interfaces(see the test):
    • <a ping='...'>
    • fetch()
    • XMLHttpRequest()
    • sendBeacon()
    • WebSocket() (hence ws:/wss: scheme can be specified in connect-src/default-src only)
    • EventSource()

    Therefore if you perform XMLHttpRequest('https://example.com/ajax') or use jQuery $ajax('https://example.com/ajax') which internally calls XMLHttpRequest(), you need to allow the https://example.com in the connect-src:
    connect-src https://example.com;
    Similarly if you use fetch('https://google.com/api/json'), you need to add this host-source to the connect-src:
    connect-src https://example.com https://google.com/api/;
    and so on for all 6 the APIs above.

    1. The script-src directive controls 5 things:
    • external scripts loading via <script src='http://example.com/script.js'></script>. You need to allow relevant host-sources in the script-src for that. Alternatively 'nonce-value'/'hash-value' token can be used.
    • inline script blocks like <script>...</script>. You need to use 'unsafe-inline' or 'nonce-value'/'hash-value' tokens in the script-src to allow such scripts.
    • eval(), setTimeout(), setInterval(), Function(), setImmediate(), execScript() funct calls are gated on the 'unsafe-eval' source expression. If you use those you need to have 'unsafe-eval' in the script-src (with some exceptions for setTimeout()/setInterval()).
    • navigation to javascript-URLs like <a href='javascript:...'>.
    • inline event handlers in tags like <div onblur='...'>, <input onclick='...'>.
      * for last 2 things you need to have 'unsafe-inline' in the script-src directive or use unsafe-hashes + 'hash-value' tokens paired (supported with some bugs as for now).
    1. The style-src directive covers several things(see the test):
    • stylesheet requests via <link href='http://example.com/min/css.css' rel='stylesheet'>. In this case you need to add http://example.com host-source to the style-src directive.
    • stylesheet requests from the CSS @import url('https://example.com/style_import.css')
    • stylesheet requests from a Link HTTP response header field Link: https://example.com/file.css; rel=stylesheet.
    • inline style blocks: <style>...</style>. You need to have 'unsafe-inline' or 'nonce-value'/'hash-value' in the style-src to allow these.
    • style= attribute in tags: <tag style='color:green; margin:0 auto;'>. You need to have 'unsafe-inline' in the style-src to allow these. Or use paired the 'unsafe-hashes' + 'hash-value' (is not widely supported as for now).
      * JS call setAttribute('style', 'display:none;') is considered as <tag style='display:none;'> above.
    • using of CSSStyleSheet.insertRule(), CSSGroupingRule.insertRule(), CSSStyleDeclaration.cssText and CSSStyleRule.selectorText was intended to be gated to 'unsafe-eval' in the style-src, but it's not implemented yet.

    Any usage of the above constructs (even via script calls) requires to allow relevant sources or tokens in the styler-src directive.