Content Security Policy (CSP)

Content Security Policy (CSP)

svierkantsvierkant Posts: 33Questions: 2Answers: 0
edited May 2021 in Free community support

I'm trying to implement CSP: Content Security Policy. Unfortunately, the usage of Datatables gives some problems.

There have been some issues on Github (https://github.com/DataTables/DataTablesSrc/issues/112).

In this case core.scrolling.js is using innerHtml(), which causes an error:

Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self' https://localhost:8080 'nonce-50RjuBbfActeF91nVpwOVw==' 'unsafe-inline' 'nonce-d3ed68246f6239fd9417b39810c79ae7'". Note that 'unsafe-inline' is ignored if either a hash or nonce value is present in the source list.

See https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML#security_considerations

For that reason, it is recommended that you do not use innerHTML when inserting plain text; instead, use Node.textContent. This doesn't parse the passed content as HTML, but instead inserts it as raw text.

and:

Warning: If your project is one that will undergo any form of security review, using innerHTML most likely will result in your code being rejected. For example, if you use innerHTML in a browser extension and submit the extension to addons.mozilla.org, it may be rejected in the review process. Please see Safely inserting external content into a page for alternative methods.

Should we change .innerHtml() in this case? Or do you have other ideas?

Replies

  • svierkantsvierkant Posts: 33Questions: 2Answers: 0

    Note that it only happens when scroll_x is true.

  • svierkantsvierkant Posts: 33Questions: 2Answers: 0
    edited May 2021

    I've looked into .textContent, but I see I'm having titles like <span class="fa fa-tags" aria-hidden="true"></span> Tags, so that isn't an option.

    What about using DOMPurify? https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Safely_inserting_external_content_into_a_page#working_with_html_content

    This is what @json-editor does:

    cleanText (txt) {
        /* Clean out HTML tags from txt */
        const tmp = document.createElement('div')
        tmp.innerHTML = txt
        return (tmp.textContent || tmp.innerText)
      }
     if (window.DOMPurify) {
        el.innerHTML = window.DOMPurify.sanitize(text);
      } else {
        el.textContent = this.cleanText(text);
      }    
    

    Pretty elegant IMHO. Checks if DOMPurify is available, otherwise uses textContent.

  • allanallan Posts: 63,516Questions: 1Answers: 10,472 Site admin

    Hi,

    I think actually we just need to rewrite that little bit of code to use proper DOM methods rather than the little innerHTML workaround. It is fast and works, but yes, it isn't idea and can lead to CSP issues. I'll get that done and comment back here when done.

    Allan

  • svierkantsvierkant Posts: 33Questions: 2Answers: 0
    edited May 2021

    Thanks! Would having html in a column name (like an icon from my example) still work in that case?

  • allanallan Posts: 63,516Questions: 1Answers: 10,472 Site admin

    Yes - my current thinking is to do a deep clone of the child nodes and then append in the clones. However, it should be noted that the elements in here aren't actually visible to the end user - they are used only to make the bowser think that the content is the same as the visible header.

    Honestly, scrolling tables are a mess! We've had to put so many tricks in to make it work properly. We've got a summer project lined up to see if we can simplify using position: sticky.

    Allan

This discussion has been closed.