Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Autoescaping improvements #577

Merged
merged 3 commits into from
Aug 9, 2018
Merged

Autoescaping improvements #577

merged 3 commits into from
Aug 9, 2018

Conversation

ollien
Copy link
Contributor

@ollien ollien commented Aug 3, 2018

Twig.js's autoescaping currently has some potentially unexpected behavior.

When autoescaping, the returned string object has a twig_markup value of true, which is unexpected and currently breaks certain usages of the twig module. For instance, you cannot insert this String as-is to your DOM, and must first call .valueOf(). I've changed the output to always return a properly formatted string, rather than this String object. This should not break any existing code, as you can still call .valueOf() on this newly returned string.

The more glaring problem however, is that the current version of twig.js doubly-escapes strings marked as html_attr with the html strategy. PHP Twig does not do this. I've added a fix for this.

Here's a quick demo of the problem. Given this template

{{ foo }}
{{ bar|escape('html_attr') }}

I've written the following test scripts in Node,

let twig = require('./src/twig.js');
let fs = require('fs');

let templateFile = fs.readFileSync('../twig-test/templates/test.html.twig', {encoding: 'utf-8'});
let template = twig.twig({data: templateFile, autoescape: 'html'});
console.log(template.render({foo: '<script>alert("hi!")</script>', bar: '" onclick="alert(\\"html_attr\\")"'}));

and in PHP.

<?php

require_once 'vendor/autoload.php';

$loader = new Twig_Loader_Filesystem('templates');
$twig = new Twig_Environment($loader, ['autoescape' => 'html']);
$template = $twig->load('test.html.twig');
echo $template->render(['foo' => '<script>alert("hi!")</script>', 'bar' => '" onclick="alert(\"html_attr\")"']);

The Node script output is as follows

&lt;script&gt;alert(&quot;hi!&quot;)&lt;/script&gt;
&amp;quot;&amp;#x20;onclick&amp;#x3D;&amp;quot;alert&amp;#x28;&amp;quot;html_attr&amp;quot;&amp;#x29;&amp;quot;

while the PHP script outputs

&lt;script&gt;alert(&quot;hi!&quot;)&lt;/script&gt;
&quot;&#x20;onclick&#x3D;&quot;alert&#x28;&#x5C;&quot;html_attr&#x5C;&quot;&#x29;&quot;

Note that the inverse operation (i.e. escaping as 'html' while using 'html_attr') does double escape in both twig.js and PHP twig.

@dave-irvine
Copy link
Contributor

@ollien Can you write a couple of tests for this? Just something that breaks before your changes and passes after your changes.

@ollien
Copy link
Contributor Author

ollien commented Aug 8, 2018

Sure. I'll get that out this afternoon.

@dave-irvine dave-irvine merged commit b8590cd into twigjs:master Aug 9, 2018
willrowe pushed a commit to willrowe/twig.js that referenced this pull request May 11, 2019
* Return value of output instead of string object

* Fix double escaping when using html_attr within html

* Add unit tests for double escaping and string object mangling
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants