33

I'm using twig 1.12.2. My code generates some elements from code-behind, when rendering these with the latest version of twig they get html-encoded

{% for item in files_folders %}
<tr class="{{ cycle(['tr_odd', 'tr_even'], loop.index) }}">
    <td><img src="../templates/images/sharepoint/{{ item.ContentType }}.gif" border="0" alt=""/></td>
    <td>{{ item.Link }}</td>
    <td>{{ item.Modified }}</td>
    <td>{{ item.FileSize }}</td>
    <td>{{ item.FileType }}</td>
</tr>
{% endfor %}

This will output this

<tr class="tr_even">
    <td><img src="../templates/images/sharepoint/Document.gif" border="0" alt=""/></td>
    <td>&lt;a href=&#039;?download=/ddd.png&#039;&gt;ddd.png&lt;/a&gt;</td>
    <td>2013-03-04 17:47:38</td>
    <td>64.8 KB</td>
    <td>png</td>
</tr>
<tr class="tr_odd">
    <td><img src="../templates/images/sharepoint/Document.gif" border="0" alt=""/></td>
    <td>&lt;a href=&#039;?download=/asdasd.png&#039;&gt;asdasd.png&lt;/a&gt;</td>
    <td>2013-03-03 20:01:52</td>
    <td>66.04 KB</td>
    <td>png</td>
</tr>

When I debug and have a look at the data before it's sent to twig it is not escaped. I haven't found any alternative to {{ item.Link }} to render data as-is.

Thanks

Eric Herlitz
  • 25,354
  • 27
  • 113
  • 157

4 Answers4

62

You can use the raw filter to make twig render raw html

http://twig.sensiolabs.org/doc/filters/raw.html

{% autoescape %}
    {{ var|raw }} {# var won't be escaped #}
{% endautoescape %}
Pastor Bones
  • 7,183
  • 3
  • 36
  • 56
romainberger
  • 4,563
  • 2
  • 35
  • 51
  • 1
    Good Answer +1 However, please include an example to ensure your answer stays relevant as links can `die` or become missing. – Pastor Bones Nov 28 '15 at 00:42
  • 4
    As always: Please be carefull when using |raw . If you raw user input, you open the gates for XSS. – Rubinum Jun 02 '17 at 13:21
  • I absolutely love this about twig - it makes sure some coder doesn't put unescaped variable content to output, unlike other template languages where e.g. `{{x}}` would do that which is harder to recognize against `{x}` in comparison with very explicit `|raw` :-) – jave.web Oct 25 '22 at 17:44
  • Here is the updated link: https://twig.symfony.com/doc/3.x/filters/raw.html – Supamic Apr 17 '23 at 21:26
18

You should be careful with using |raw. Saying that the data is safe, means you are trusting it 100%.

Personally I would suggest using a custom twig filter:

class CustomExtension extends \Twig_Extension 
{
    public function getFilters()
    {
        return array(
            new \Twig_SimpleFilter('unescape', array($this, 'unescape')),
        );
    }

    public function unescape($value)
    {
        return html_entity_decode($value);
    }
}

Add the following to your services.yml (or alternatively translate into xml).

 services:
     ha.twig.custom_extension:
     class: HA\SiteBundle\Twig\CustomExtension
     tags:
         - { name: twig.extension }
Gounzy
  • 23
  • 4
Paul Danelli
  • 994
  • 1
  • 15
  • 25
  • This is elegant but in applications that are not communities or public facing web sites the 100% trust isn't really an issue :) – Eric Herlitz Jul 23 '14 at 20:45
  • 2
    I agree, but it should still be a consideration, protecting the developer from themselves for example. – Paul Danelli Jul 25 '14 at 07:56
16

Or http://twig.sensiolabs.org/doc/filters/raw.html

{% autoescape false %}
   {{ your_item }}{# your_item won't be escaped #}
{% endautoescape %}
Promo IL
  • 167
  • 1
  • 8
5

If you are using Drupal 8 and none of raw or autoscape works, this could happen because of the variable you're trying to print if it's a render array with a template holding a safe output (for example, a hl2br filter).

I that case, you would need to access the value through the render array and filter it, for instance:

{% autoescape false %}
  {{ item.content['#context']['value'] }}
{% endautoescape %}
Juan De León
  • 361
  • 3
  • 7