Автоматически ли setAttribute экранирует символы HTML?

Я исследую ошибку в нашей системе, когда атрибут заголовка ссылки устанавливается на что-то вроде 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 API, а не клиент.

Daniel A. White 02.05.2018 20:12

да, я предположил, что «реализация» - это причудливое универсальное слово для браузера / DOM.

Inondle 02.05.2018 20:22
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
2
1 181
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Не совсем.

HTML - это формат данных.

Браузеры проанализируют HTML и сгенерируют из него DOM. Именно в этот момент ссылки на символы (например, >) преобразуются в символы, которые они представляют (например, >).

Когда вы используете setAttribute, вы напрямую изменяете DOM.

Это полностью обходит формат данных HTML, поэтому HTML foo = "&" и JavaScript setAttribute("foo", "&") дадут вам одинаковый конечный результат.

а почему < не экранирован? попробуйте a.setAttribute('a', 'a<s');console.info(a.outerHTML);

Vytautas Jakutis 24.03.2020 18:56

@VytautasJakutis - вы не можете начинать тег в середине значения атрибута, поэтому < не означает «запускать тег» там, поэтому его не нужно экранировать.

Quentin 24.03.2020 23:46

попробуйте это, посмотрите несоответствие в externalHTML: <div id = "a" a = "&amp;"></div> <div id = "b" b = "&gt;"></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', '&amp;') + attr('b', '&gt;')) </script>

Vytautas Jakutis 07.04.2020 19:10

@VytautasJakutis - Это вызывает исключение: jsbin.com/bebuzazuwi/1/edit?html,output

Quentin 07.04.2020 20:26

здесь исправлено jsbin.com/mojevidida/edit?html,console,output - посмотрите на строки 4 и 5 в сравнении с 1 и 2 - externalHTML экранирует &, но не <- вы можете фактически запустить тег в середине атрибута.

Vytautas Jakutis 09.04.2020 07:35

@VytautasJakutis - нельзя начинать тег в середине значения атрибута. В середине значения атрибута < не означает, что «начать тег» означает «меньше символа». Поэтому я сказал, что этого не нужно убегать. Следовательно, почему это не экранировано в вашем примере. & внутри значения атрибута делает означает «Начать ссылку на символ или объект», поэтому делает необходимо экранировать.

Quentin 09.04.2020 10:31

тогда почему для <?xml version = "1.0" encoding = "UTF-8"?><tag one = "<two>"></tag> xmllint не работает с: «a.xml: 1: ошибка парсера: неэкранированный '<' не допускается в значениях атрибутов»?

Vytautas Jakutis 10.04.2020 12:17

@VytautasJakutis - Это не HTML.

Quentin 10.04.2020 12:21

тот же сбой xmllint для <tag one = "<two>"></tag>, это должен быть HTML? так как это будет вывод .outerHTML

Vytautas Jakutis 11.04.2020 13:05

@VytautasJakutis - Почему это должен быть HTML? В HTML нет элемента <tag>, и вы используете XML Lint для его тестирования.

Quentin 11.04.2020 14:52
<tag one = "<two>"></tag> является результатом .outerHTML, поэтому он должен быть HTML - var tag = document.createElement('tag');tag.setAttribute('one', '<two>');console.info(tag.outerHTML).
Vytautas Jakutis 12.04.2020 15:17

если вам нужны HTML-теги, вот и та же проблема: var div = document.createElement('div');div.setAttribute('data-one', '<two>');console.info(div.outerHTML)

Vytautas Jakutis 12.04.2020 15:25

@VytautasJakutis - XMLLint не знает и не заботится о том, что вы сгенерировали данные с помощью инструмента, предназначенного для генерации HTML. Он обрабатывает его как XML, потому что это линтер для XML.

Quentin 12.04.2020 17:20

хорошо, понятно, спасибо за аргументы и подтверждение, что нельзя использовать сериализатор HTML для генерации XML :)

Vytautas Jakutis 13.04.2020 19:10
Ответ принят как подходящий

Простая английская интерпретация этой цитаты заключается в том, что setAttribute() не анализирует значение как HTML. Причина в том, что вы вообще не пишете HTML; значение находится в обычном тексте, а не в HTML, поэтому специальные символы в HTML не имеют особого значения в обычном тексте, и их экранирование, как если бы они были HTML, на самом деле было бы разрушительным.

&gt; - это HTML-представление >. Вам нужно только закодировать его в HTML, а не в виде обычного текста.

Другие вопросы по теме