Render function uses InnerHTML with partly escaped HTML entities

Render function uses InnerHTML with partly escaped HTML entities

dmthomasdmthomas Posts: 3Questions: 1Answers: 0

Hello,
I am trying to use the colum render callback function in order to modify the cells.
The render function has 4 parameters (documentation at https://datatables.net/reference/option/columns.render )
The function signature is "function render( data, type, row, meta )"

Unfortunately, the HTML entities are partly encoded and partly decoded.
Example:

<tr>
<td>Tiger &amp; &uuml; &quot; &szlig; &lt; &gt; Nixon</td>
<td>System Architect</td>
</tr>

The render function unfortunately gets the HTML entities partly encoded.

Thus when I encode the return value, some entities are double encoded. If i dont encode the return value, somebody
can inject Javascript.

I think the problem goes back to the usage of the innerHTML element.
The use of InnerHTML is disregarded by Mozilla because of these buggy HTML entity encoding:
https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML

Is there a way to use the render function in a save way without JS injection and without double encoding?
The usage of textContent is recommended by Mozilla but this might be a bigger change in the library.

A little example is attached with a break point at the render function.

Many thanks in advance,
Thomas

This question has an accepted answers - jump to answer

Answers

  • allanallan Posts: 61,635Questions: 1Answers: 10,092 Site admin

    Yes, that's nasty. We use innerHTML primarily because of how fast it is, and also to allow for HTML content (for example it would be valid to have <td><em>Allan</em</td>) and expect the HTML to be displayed correctly. Using textContent wouldn't allow for that unfortunately.

    What we could potentially do is provide an option to allow a switch between using innerHTML and textContent - then you can make a judgement on your own use case.

    Another option would be to Ajax load your data rather than having it read from the HTML, which would effectively side set this issue since the data wouldn't be HTML encoded and you could use our built in text renderer to prevent against XSS attacks.

    Allan

  • dmthomasdmthomas Posts: 3Questions: 1Answers: 0

    Hello Allan,
    thanks for your answer.
    We are using HTML also to convert text to links for example.
    So you are right, that textContent would not work in that case, unfortunately.

    Also using Ajax to fill the grid has the same problem, if we want to use the render function for formating the cell.

    The only two remaining solutions which come into my mind are:
    1) Pre-Format the JSON/AJAX or the cell data in advance and not use the render function.
    2) Encode the string and taking the quirky specification of innerHTML into account, dealing with the 3 special entities.

    I dont know why innerHTML decodes all entities but three.
    Using Unicode-Encoding like &#x3c; doesn't help either.

    If you have any further possible solutions left, please drop a line.

    Thank you very much,
    Thomas

  • allanallan Posts: 61,635Questions: 1Answers: 10,092 Site admin
    Answer ✓

    Another option, and the one I use in CloudTables is to have the data in a “safe” format and then transform it into the HTML to be displayed - e.g. the data for the cell might be:

    [
      { type: ‘text’, value: ‘Start’ },
      { type: ‘link’, href: ‘//cloudtables.com’, value: ‘CloudTables’ }
    ]
    

    And then render that out to HTML. Then you are generating the markup and can safely encode the content that should be displayed to the end user. Similarly Markdown could be used, although perhaps a bit more processing heavy for output.

    Allan

  • dmthomasdmthomas Posts: 3Questions: 1Answers: 0

    Hello Allan,
    unfortunately we need to show a text field which originates from a user input.
    As user input must be considered unsafe, I think we must go for 1) or 2).

    Thank you for your input, information and your view about this topic!

    Happy easter,
    Thomas

This discussion has been closed.