0
votes

I have a Symfony website where users can mention others when commenting on posts. When the comments rendered, if there are "<"script">" tags they are also being executed as javascript.

Example comment in the database: I think <a href="https://www.examplesite.com/burak">@joanna</a> was right

When I render this comment without a "raw" filter the HTML tags are being escaped and the problem disappears. However, the whole link shows up in the comments and mentions are not being clickable anymore.

I tried the custom filter below but that did not work either.

class FilterBlackListedExtension extends \Twig_Extension
{

private $blacklistedTags = ['script', 'p'];

public function getFilters()
{
    return array(
        new \Twig_SimpleFilter('filter_black_listed', array($this, 'htmlFilter')),
    );
}

public function htmlFilter($html)
{
    foreach ($this->blacklistedTags as $tag) {
        preg_replace('/(<' . $tag . '>)(.*)(<\/' . $tag . '>)/', '', $html);
    }

    return $html; // maybe even apply the raw filter also afterwards.
}

public function getName()
{
    return 'filter_black_listed_extension';
}

}

What I exactly need is a filter that will escape javascript but not HTML. Note: I already tried escape("js") and that did not work too. It also brought up hex like characters in the comment.

2
If you want to implement just the "mention" feature i think you should not allow users to save HTML, but instead transform the mention data into a structure that will help you generate the output on render time. e.g input-> "I think @joanna was right"-> before you save that string into the DB you transform it for example to "I think [mention-user-id=42]@joanna[/mention] was right". And then you will create a Twig filter that parses those tags and generates anchors instead. Or you could instead save the message as plain text and save in another field the data to generate the link.knetsi

2 Answers

3
votes

If you want to allow some HTML but avoid scripts, then you can use a tool like HTMLPurifier. This will parse the HTML and apply a custom whitelist to it.

1
votes

You can use the Twig striptags filter to escape all tags except the ones you want to preserve. To remove html tags but keep the links in your comments, do this:

{{ comment_content|striptags('<a>') }}

The filter's argument is a whitelist of tags. If you want to preserve other tags just add them to the string:

{{ comment_content|striptags('<a><p><strong>') }}

For information, using escape("js") didn't work because it's meant to escape in a javascript context, which means within a script.


Warning : as pointed out by @fgb, javascript inserted in tags via event attributes like
<a onmouseover='alert(1)'>123</a> would be executed with this solution.