Generating safe markup in Drupal 8
The most insecure part of a Drupal website is typically the theme. Drupal 8 is using Twig as its template layer. This is a massive leap forward. It's no longer possible to put SQL queries in a template file!
Furthermore, Drupal 8 is now taking advantage of a security feature of Twig: autoescape. Every variable in a Twig template will be escaped if it is not marked as safe. This makes it much harder to introduce XSS vulnerabilities.
Unfortunately any HTML that your module produces will end up being double-escaped and the HTML itself will be visible instead of the browser's rendering of it. The quick and dirty way to fix this problem is to wrap your string with \Drupal\Component\Utility\SafeMarkup::set:
<span style="color: #000000"><span style="color: #0000BB"><?php<br>$output </span><span style="color: #007700">= </span><span style="color: #0000BB">SafeMarkup</span><span style="color: #007700">::</span><span style="color: #0000BB">set</span><span style="color: #007700">(</span><span style="color: #DD0000">'<div class="my-module">' </span><span style="color: #007700">. </span><span style="color: #0000BB">$my_variable </span><span style="color: #007700">. </span><span style="color: #DD0000">'<div>'</span><span style="color: #007700">);<br></span><span style="color: #0000BB">?></span></span>
But this defeats the whole point of using autoescape. The correct approach is that all HTML created by a module should be declared in a Twig template. This means that all the variables are guaranteed to be escaped. It is also very easy to implement.
First you need to declare the template in your hook_theme():
<span style="color: #000000"><span style="color: #0000BB"><?php<br></span><span style="color: #007700">function </span><span style="color: #0000BB">my_module_theme</span><span style="color: #007700">(array </span><span style="color: #0000BB">$existing</span><span style="color: #007700">, </span><span style="color: #0000BB">$type</span><span style="color: #007700">, </span><span style="color: #0000BB">$theme</span><span style="color: #007700">, </span><span style="color: #0000BB">$path</span><span style="color: #007700">) {<br> return array(<br> </span><span style="color: #DD0000">'my_module_my_template' </span><span style="color: #007700">=> array(<br> </span><span style="color: #DD0000">'template' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'my-template'</span><span style="color: #007700">,<br> </span><span style="color: #DD0000">'variables' </span><span style="color: #007700">=> array(<br> </span><span style="color: #DD0000">'variable1' </span><span style="color: #007700">=> </span><span style="color: #0000BB">NULL</span><span style="color: #007700">,<br> </span><span style="color: #DD0000">'variable2' </span><span style="color: #007700">=> </span><span style="color: #0000BB">NULL</span><span style="color: #007700">,<br> ),<br> ),<br> );<br>}<br></span><span style="color: #0000BB">?></span></span>
You then need to create a Twig template file, for example my_module/templates/my-template.html.twig:
{#<br>/**<br> * @file<br> * Default theme implementation for my template.<br> *<br> * Available variables<br> * - variable1: The first variable.<br> * - variable2: The second variable.<br> */<br>#}<br><div class="my-template"><br> This is the first variable: <b>{{ variable1 }}</b>.<br> This is the second variable: <i>{{ variable2 }}</i>.<br></div>
When you need to generate your html you should use the drupal_render() function:
<span style="color: #000000"><span style="color: #0000BB"><?php<br>$render </span><span style="color: #007700">= array(<br> </span><span style="color: #DD0000">'#theme' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'my_module_my_template'</span><span style="color: #007700">,<br> </span><span style="color: #DD0000">'#variable1' </span><span style="color: #007700">=> </span><span style="color: #0000BB">t</span><span style="color: #007700">(</span><span style="color: #DD0000">"First"</span><span style="color: #007700">),<br> </span><span style="color: #DD0000">'#variable2' </span><span style="color: #007700">=> </span><span style="color: #0000BB">t</span><span style="color: #007700">(</span><span style="color: #DD0000">"Second"</span><span style="color: #007700">),<br>);<br><br></span><span style="color: #0000BB">$output </span><span style="color: #007700">= </span><span style="color: #0000BB">drupal_render</span><span style="color: #007700">(</span><span style="color: #0000BB">$render</span><span style="color: #007700">);<br></span><span style="color: #0000BB">?></span></span>
Strings returned by drupal_render() are automatically marked as safe and will not be escaped again.