2.0.5
http://codepen.io/anon/pen/pNbQeY
{{
and }}
)Curly braces in non-app, user content are ignored. Especially when encoded.
User can crash Vue and thus the application by simply using the curly braces syntax anywhere their input is rendered, i.e. {{ myvalue }}
and {{ myvalue }}
.
{{ myvalue }}
v-html
.v-html
syntax, which prevents using third-party, non-Vue code they have no access to.delimiters: ['', '']
which causes Vue to render every single element. Vue.config({ interpolate: false })
(https://github.com/vuejs/vue/issues/147#issuecomment-36372431) or a non-global option per Vue instance.v-ignore-delimiters
or v-disable-interpolation
, to disable {{ myvalue }}
rendering inside that HTML tag, but still allow it to be altered using Vue or act as a Vue component.Perhaps I'm completely missing the point, but at the moment, this prevents me from using Vue in my app. I didn't think this would be a major issue, yet it's proven itself to be quite cumbersome to fix or bypass. Not sure how others handle this situation. Would love to get some feedback on this and be able to continue development using Vue.
If you are using vue why aren't you loading user content through vue. If you place curly braces inside a data property you can output them and there are no problems.
Because all content is loaded and rendered server-side using Laravel and Blade templates. It's not a single page application that's built entirely in JS. I don't even load any data using JS, I'm merely using Vue and its awesome components to optimize the user's experience (client-side).
馃槺 I feel like such a dumbass now. I've spent hours looking around in those docs. Thank you!
v-pre also disables attribute parsing though.
i.e. if you have:
<div id="app" v-pre>
<p v-text="2+2"></p>
</div>
It won't show 4.
Since HTML escaping should already be done by all applications a way to disable only moustache interpolation would be nice. I'm currently doing this by setting the delimiters to a long random string but it is sort of hacky.
Clearly, v-pre
doesn't really answer the original question (which was _"Disable interpolation"_ and not _"Disable parsing"_).
v-pre
doesn't allow to use Vue.js on pages where there is user content _and_ Vue.js components at the same timeSee, if one uses v-pre
on the root element, the entire root element is not parsed, including all Vue.js components, basically making it useless. To allow components to work, v-pre
must be used on all user input separately.
But this will not work (in the long run). Template authors will forget to do that. This is a time bomb, very similar to the old times when we used raw PHP3 and had to call htmlspecialchars()
on all user input to prevent XSS, but this time it's even worse since we now have "smart" server-side frameworks which emit supposedly "safe" HTML for us (which turns out to be unsafe with Vue.js!)
For example, let's say we use Django forms framework and have Edit User Profile page template:
<form method="post">
{{ user_form.name }}
<button>Save</button>
</form>
It will emit <input type="text" value="(escaped user name)">
. This works very well until this code runs inside a Vue app.
If a user submits "{{ var }}" (literally) for his name, just for lulz, the HTML code will become <input ... value="{{ var }}">
, and the entire page will crash and become empty (with _"Interpolation inside attributes has been removed"_ error).
At the same time, it's very inconvenient to guard each and every surrounding element with v-pre
. Sometimes it's not even possible: for example, I might like the button caption to be rendered with Vue depending on the app state.
And of course, if the user's new funny name is saved into the database and then rendered somewhere else with {{ user.name }}
(Django code) without explicit v-pre
, it will crash Vue.js and show empty page for all other users (with _"avoid using JavaScript keyword as property name: "var"_ error). Bummer!
Below is a quick hack that I came up with:
const noDelimiter = {replace: () => '(?!x)x'}; // return a non-matching regexp.
const app = new Vue({
el: '#vue-app',
delimiters: [noDelimiter, noDelimiter],
components: {
MyComponent,
},
});
Just in case, pulling app vars will still be possible with v-text
.
@IlyaSemenov
This way is not enough.
Because, it enables interpolation with undefined syntax.
<div id="app">
undefined message undefined
</div>
<script>
const noDelimiter = {replace: function(){}};
const app = new Vue({
el: '#app',
delimiters: [noDelimiter, noDelimiter],
data: {
message: 'Hello Vue!'
}
});
</script>
Result
Hello Vue!
so, I created pr.
https://github.com/vuejs/vue/pull/6203
@alfa-jpn Good point, I didn't pay attention to what happens to the result of the replace
call. Since it's simply concatenated to construct a regexp, returning any non-matching regexp should work. I've updated my example above correspondingly.
Is there a specific reason why Vue renders {{ myvalue }}
? Adding v-pre everywhere may not be the best solution for server-side rendered templates as it's very hard to ensure complete coverage.
Most helpful comment
http://vuejs.org/v2/api/#v-pre