setAttribute自动转义HTML字符吗?

4
我正在调查我们系统中的一个错误,其中链接的标题属性被设置为类似于click if value > 400,但实际显示的工具提示是click if value > 400。该标题值由用户输入定义,因此原始工程师对文本进行了转义,以避免引起XSS漏洞。click if value > 400变为click if value > 400
这个额外的转义步骤似乎导致HTML特殊字符过度转义,因此它们的转义值被文字渲染出来。
为了更加彻底,我检查了HTML规范,根据这行说明,setAttribute函数必须自动转义属性值字符串。

https://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-F68F082

如果元素中已经存在该名称的属性,则将其值更改为value参数的值。该值是一个简单的字符串;在设置时它不会被解析。因此,任何标记(例如要识别为实体引用的语法)都被视为字面文本,并且在写出时需要由实现适当地进行转义。
据我理解,这句话意味着setAttribute函数应该转义HTML特殊字符。这个解释正确吗?

“通过实现”我认为指的是Web浏览器或DOM API,而不是客户端。 - Daniel A. White
是的,我以为“implementation”是指浏览器/DOM的通用术语。 - Inondle
2个回答

5
那段引语的简明解释是,setAttribute()不会将值解析为HTML。原因在于你根本没有编写HTML; 值是纯文本,而不是HTML,因此在纯文本中通常具有特殊意义的HTML特殊字符在这里没有特殊含义,对它们进行转义就会破坏它们。
> 是 > 的HTML表示形式。你只需要将它编码为HTML,而不是纯文本。

2

并不完全正确。

HTML是一种数据格式。

浏览器会解析HTML并从中生成DOM。在这个过程中,字符引用(比如>)会被转换成它们所代表的字符(比如>)。

当你使用setAttribute时,你会直接改变DOM。

这完全绕过了HTML数据格式,因此HTML中的foo="&"和JavaScript中的setAttribute("foo", "&")将得到相同的结果。


但为什么 < 没有被转义?尝试使用 a.setAttribute('a', 'a<s');console.log(a.outerHTML); - Vytautas Jakutis
尝试一下,查看outerHTML中的不一致性:<div id="a" a="&"></div><div id="b" b=">"></div> <script> const attr = (name, escaped) => { const div = document.getElementById(name) let out = [name, div.getAttribute(name), div.outerHTML, '\n'] div.setAttribute(name, div.getAttribute(name)) out += [name, div.getAttribute(name), div.outerHTML, '\n'] div.setAttribute(name, escaped) out += [name, div.getAttribute(name), div.outerHTML, '\n'] return out } console.log(attr('a', '&') + attr('b', '>')) </script> - Vytautas Jakutis
@VytautasJakutis — 这会抛出一个异常:https://jsbin.com/bebuzazuwi/1/edit?html,output - Quentin
请看这个链接 https://jsbin.com/mojevidida/edit?html,console,output - 观察第4和5行与第1和2行的不同之处 - outerHTML转义了&,但没有转义< - 实际上你可以在属性中间开始一个标签。 - Vytautas Jakutis
1
@VytautasJakutis — XMLLint并不知道也不关心你是用一个设计用于生成HTML的工具来生成数据。它将其视为XML,因为它是XML的linter。 - Quentin
显示剩余9条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接