I am working on a blog comment bundle and I would like to let user post some code using Markdown.
I am working with symfony2, TWIG and KNPMarkdownBundle for parsing
{{ post.content|markdown }}
Actually, the content is well markdown parsed (<code>
<p>
...) but if I have some HTML code in my content like :
Some content
``` <script>alert("hello world");</script> ```
The code is not escaped and I have a alert message.
Please can someone explain how can I deal with XSS issues ? (foo|raw
and foo|escape
are breaking parsing)
As @sjagr hinted, you better write your own twig extension. Once upon a time I've run into a similar issue and have just written a simple extension to sort it which was very simple and easy.
NEW TWIG TAG:
{{ post.content|yourNewTag }}
NEW TWIG EXTENSION CLASS:
namespace Car\BrandBundle\Twig;
class YourNewTagExtension extends \Twig_Extension
{
public function yourNewTagFilter($param)
{
// Escape your content as you wish with some logic and return it
return $escaped;
}
public function getFilters()
{
return array(new \Twig_SimpleFilter('yourNewTag', array($this, 'yourNewTagFilter')));
}
public function getName()
{
return 'yourNewTag_extension';
}
}
CONFIG:
services:
car.twig.yourNewTag_extension:
class: Car\BrandBundle\Twig\YourNewTagExtension
tags:
- { name: twig.extension }
EDIT:
TWIG:
{% set someContent = '<script>alert("hello world");</script>' %}
{{ someContent|yourNewTag }}
If you don't want to escape specific tags then use allowable_tags flag with strip_tags() function.
public function yourNewTagFilter($param)
{
$escaped = strip_tags($param);
// Do something else as well if you want
return $escaped;
// This will print alert("hello world"); as output in your webpage
}
I just happened to have this problem, but since strip_tags
is not enough to protect values in the attributes tag, I will submit my answer.
I'm using HTML Purifier to remove all unwanted HTML elements and attributes. Open a command console and execute the following command to install it.
$ composer require ezyang/htmlpurifier "^4.6"
Then you can create your own Twig extension:
namespace AcmeBundle\Twig;
class HTMLPurifierExtension extends \Twig_Extension
{
public function getFilters()
{
return array(
new \Twig_SimpleFilter('html_purifier', array($this, 'purify'), array('is_safe' => array('html'))),
);
}
public function purify($text)
{
$elements = array(
'p',
'br',
'small',
'strong', 'b',
'em', 'i',
'strike',
'sub', 'sup',
'ins', 'del',
'ol', 'ul', 'li',
'h1', 'h2', 'h3',
'dl', 'dd', 'dt',
'pre', 'code', 'samp', 'kbd',
'q', 'blockquote', 'abbr', 'cite',
'table', 'thead', 'tbody', 'th', 'tr', 'td',
'a[href|target|rel|id]',
'img[src|title|alt|width|height|style]'
);
$config = \HTMLPurifier_Config::createDefault();
$config->set('HTML.Allowed', implode(',', $elements));
$purifier = new \HTMLPurifier($config);
return $purifier->purify($text);
}
public function getName()
{
return 'html_purifier';
}
}
Open services.yml
and register the extension as a service:
services:
acme.html_purifier_extension:
class: AcmeBundle\Twig\HTMLPurifierExtension
public: false
tags:
- { name: twig.extension }
Now you can use it with
{{ post.content|markdown|html_purifier }}
You can use Twig's striptags
filter just like you would PHP's strip_tags function to allow particular HTML tags through:
{{ post.content|striptags('<code><p><br>')|markdown }}
This will eliminate unwanted tags entirely instead of parsing them to <
and >
as well.
Aside from this though, you may want to write your own Twig filter in case you want to easily reference the same set of "allowed tags" every time.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With