Search code examples
javascriptescapingdust.jshtml-escape-characters

How can I stop DustJS converting entities back to normal characters?


To replicate my problem, go here, and please paste this code into corresponding sections:

Dust Template:

{title|s}

Data:

{
  "title": "<script>alert('yo');</script>"
}

You will see following output:

<script>alert('yo');</script>

In my opinion it's a wrong behaviour, as entities are converted back to normal characters. Which results in alert being executed.

I want to control whether value I'm inserting to my template is HTML-escaped or not via JS. So Dust JS shouldn't do any smart operations behind, and just feed the template with exactly the content I want. How can I achieve that?


Solution

  • |s seems to stand for supressing any additional escaping routines done by the library. Since you're entering your data as escaped HTML already, it spits out exactly what you gave it. The browser is rendering it as <script>alert('yo');</script>, but behind the scenes it's still &lt;script&gt;alert('yo');&lt;/script&gt; No alert is executed since your string is already escaped:

    var data = {
      "title": "&lt;script&gt;alert('yo');&lt;/script&gt;"
    };
    
    //innerHTML version
    var src = document.getElementById('template-s').textContent;
    var compiled = dust.compile(src, 'output-s');
    
    dust.loadSource(compiled);
    
    dust.render('output-s', data, function(err, out) {
      document.getElementById('output-s').innerHTML = out;
    });
    
    // textContent version
    
    src = document.getElementById('template-s-textContent').textContent;
    compiled = dust.compile(src, 'output-s-textContent');
    
    dust.loadSource(compiled);
    
    dust.render('output-s-textContent', data, function(err, out) {
      document.getElementById('output-s-textContent').textContent = out;
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/dustjs-linkedin/2.7.3/dust-full.js"></script>
    <script type="text/dust" id="template-s">Output {title|s}</script>
    <script type="text/dust" id="template-s-textContent">Output {title|s}</script>
    
    <h3>Flag: |s set as innerHTML</h3>
    <div id="output-s"></div>
    <h3>Flag: |s set as textContent</h3>
    <div id="output-s-textContent"></div>

    This article seems to do a better job of explaining the filters than the official docs. His example has an unescaped string that illustrates when alert will be executed depending on the flag you use.