使用最新的主干和下划线库 (1.0.0/1.4.4) 我无法弄清楚为什么我的模板没有像我预期的那样转义。这是一个简化版本:
M = Backbone.Model.extend({});
V = Backbone.View.extend({
template: _.template("<%- attr %>"),
render: function() {
this.$el.html(this.template(this.model.attributes));
return this;
}
});
m = new M({attr: "<script>bad</script>"});
v = new V({model: m});
v.render();
console.log(v.el);
结果是:
<div><script>bad</script></div>
显然,这并没有逃脱。我已经验证了作为独立代码执行的模板可以正确转义:
T = _.template("<%- attr %>");
console.log(T({attr: "<script>bad</script>"}));
产生预期的结果
<script>bad</script>
因此,某处的内容没有转义。如果有人知道在哪里,或者更好的是如何防止它,我将不胜感激。
斯蒂芬
更新:
弄清楚了!尽管问题不在于控制台本身,但mu的回答确实为我指明了正确的方向。为了解释,我需要对上面的示例代码进行一些详细说明,以便它更准确地反映我的上下文。该上下文实际上不是控制台输出,而是单元测试。我想验证我的代码是否正确地防止了 XSS 攻击,所以我编写了单元测试(使用 mocha/sinon/chai/should):
v.$el.text().should.equal(m.escape("attr"));
该测试失败(出乎意料),而以下测试通过(我认为它不应该):
v.$el.text().should.equal(m.get("attr"));
罪魁祸首原来是toString()
元素对象上的方法。该方法console.log()
使用,对内容进行转义。text()
jQuery 在函数中也(间接)使用了该方法。
我不确定这在所有浏览器中是否通用,但在我的情况下,使用.innerHTML()
可以避免toString()
转义。所以写我的测试的正确方法是
v.el.innerHTML().should.equal(m.escape("attr"));