Я исследую ошибку в нашей системе, когда атрибут заголовка ссылки устанавливается на что-то вроде 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. Это правильная интерпретация?
да, я предположил, что «реализация» - это причудливое универсальное слово для браузера / DOM.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Не совсем.
HTML - это формат данных.
Браузеры проанализируют HTML и сгенерируют из него DOM. Именно в этот момент ссылки на символы (например, >) преобразуются в символы, которые они представляют (например, >).
Когда вы используете setAttribute, вы напрямую изменяете DOM.
Это полностью обходит формат данных HTML, поэтому HTML foo = "&" и JavaScript setAttribute("foo", "&") дадут вам одинаковый конечный результат.
а почему < не экранирован? попробуйте a.setAttribute('a', 'a<s');console.info(a.outerHTML);
@VytautasJakutis - вы не можете начинать тег в середине значения атрибута, поэтому < не означает «запускать тег» там, поэтому его не нужно экранировать.
попробуйте это, посмотрите несоответствие в externalHTML: <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.info(attr('a', '&') + attr('b', '>')) </script>
@VytautasJakutis - Это вызывает исключение: jsbin.com/bebuzazuwi/1/edit?html,output
здесь исправлено jsbin.com/mojevidida/edit?html,console,output - посмотрите на строки 4 и 5 в сравнении с 1 и 2 - externalHTML экранирует &, но не <- вы можете фактически запустить тег в середине атрибута.
@VytautasJakutis - нельзя начинать тег в середине значения атрибута. В середине значения атрибута < не означает, что «начать тег» означает «меньше символа». Поэтому я сказал, что этого не нужно убегать. Следовательно, почему это не экранировано в вашем примере. & внутри значения атрибута делает означает «Начать ссылку на символ или объект», поэтому делает необходимо экранировать.
тогда почему для <?xml version = "1.0" encoding = "UTF-8"?><tag one = "<two>"></tag> xmllint не работает с: «a.xml: 1: ошибка парсера: неэкранированный '<' не допускается в значениях атрибутов»?
@VytautasJakutis - Это не HTML.
тот же сбой xmllint для <tag one = "<two>"></tag>, это должен быть HTML? так как это будет вывод .outerHTML
@VytautasJakutis - Почему это должен быть HTML? В HTML нет элемента <tag>, и вы используете XML Lint для его тестирования.
<tag one = "<two>"></tag> является результатом .outerHTML, поэтому он должен быть HTML - var tag = document.createElement('tag');tag.setAttribute('one', '<two>');console.info(tag.outerHTML).
если вам нужны HTML-теги, вот и та же проблема: var div = document.createElement('div');div.setAttribute('data-one', '<two>');console.info(div.outerHTML)
@VytautasJakutis - XMLLint не знает и не заботится о том, что вы сгенерировали данные с помощью инструмента, предназначенного для генерации HTML. Он обрабатывает его как XML, потому что это линтер для XML.
хорошо, понятно, спасибо за аргументы и подтверждение, что нельзя использовать сериализатор HTML для генерации XML :)
Простая английская интерпретация этой цитаты заключается в том, что setAttribute() не анализирует значение как HTML. Причина в том, что вы вообще не пишете HTML; значение находится в обычном тексте, а не в HTML, поэтому специальные символы в HTML не имеют особого значения в обычном тексте, и их экранирование, как если бы они были HTML, на самом деле было бы разрушительным.
> - это HTML-представление >. Вам нужно только закодировать его в HTML, а не в виде обычного текста.
«по реализации», я думаю, означает веб-браузер или DOM API, а не клиент.