§

Ввод

Режим
Стиль сущности
Область кодирования
§

Результат

Требования ГОСТ Р 56939-2016 по безопасной разработке программного обеспечения прямо указывают на экранирование вывода как ключевую меру защиты от XSS-атак в государственных информационных системах. ФСТЭК в методических рекомендациях по защите ГИС требует применять контекстное кодирование HTML-сущностей для любых пользовательских данных, отображаемых в браузере. Яндекс.Облако в документации по WAF описывает экранирование HTML-символов как базовый уровень защиты веб-приложений от инъекций — ещё до применения сигнатурных правил. При аттестации ГИС по требованиям ФСТЭК проверяющие отдельно запрашивают доказательства контекстного кодирования на уровне шаблонизатора. Этот инструмент работает полностью в браузере — исходный текст не покидает рабочую станцию.

Как работает кодирование HTML-сущностей

HTML-сущность — это символьная ссылка, которую браузер разбирает обратно в один символ. Пять зарезервированных HTML-символов (<, >, &, ", ') всегда требуют кодирования при отображении текста в HTML; всё остальное — по необходимости, в зависимости от кодировки документа.

  1. Выберите режим и область. Режим кодирования обходит ввод посимвольно. Режим декодирования ищет в тексте паттерны сущностей. Переключатель области определяет, кодируются ли только пять HTML-символов или все не-ASCII символы.
  2. Выберите стиль сущности. Именованные сущности (&copy;) хорошо читаются в исходном коде. Десятичные (&#169;) и шестнадцатеричные (&#xA9;) ссылки охватывают все кодовые точки Unicode без имён. Старые почтовые клиенты и XML-парсеры предпочитают числовые форматы.
  3. Обход ввода. При кодировании каждая кодовая точка ищется во встроенной таблице около 200 распространённых именованных сущностей. Если совпадения нет, используется числовой формат. При декодировании применяется одно регулярное выражение, совпадающее с &name;, &#NNN; и &#xHH; за один проход.
  4. Сопоставление с символами. Именованные совпадения разрешаются через обратную таблицу. Числовые совпадения обрабатываются через String.fromCodePoint с основанием 10 или 16. Неизвестные именованные сущности остаются нетронутыми, чтобы частичный ввод не терял данных.
  5. Режим реального времени. Включите режим реального времени, и каждое нажатие клавиши будет перезапускать преобразование с задержкой 150 мс. Удобно при доработке фрагмента, когда нужна мгновенная обратная связь перед вставкой в шаблон.

Зачем кодировать HTML-сущности

  • Предотвращение поломки вёрстки. Если пользователь вводит лишний символ < в поле комментария, и этот текст попадает прямо в HTML, браузер перепишет остаток страницы. Предварительное кодирование зарезервированных символов заставит браузер отобразить символ, а не интерпретировать его как начало тега.
  • Корректность значений атрибутов. Встраивание строки в кавычках внутри HTML-атрибута требует замены кавычки на &quot; (для атрибутов в двойных кавычках) или &#39; (для одинарных). Иначе парсер преждевременно закроет атрибут, а остаток строки станет лишней разметкой.
  • Обезвреживание HTML в хранимых данных. Логи, отчёты об ошибках и экспорт чатов часто содержат угловые скобки и амперсанды. Кодирование дампа перед вставкой в документацию оставляет содержимое видимым как текст вместо того, чтобы запустить рендерер или автодетектор ссылок.
  • Безопасный обмен фрагментами кода. Публикация примера тега вроде <script>alert(1)</script> в блог-посте, письме или сообщении требует кодирования скобок, чтобы фрагмент отображался, а не выполнялся. Та же техника применима к телам RSS-лент и полям `description` в JSON-LD.

Типичные случаи применения

Кодирование сущностей встречается везде, где необработанный текст составляется в HTML во время выполнения — даже когда фреймворк обычно делает это за вас, ручной инструмент полезен в случаях, когда автоматика отключена.

  • Серверные шаблоны: Jinja2, ERB, Twig и Handlebars автоматически экранируют по умолчанию, но блоки raw и маркеры `safe` это отключают — кодек позволяет проверить, что именно произвело бы экранирование.
  • Электронные письма и рассылки: многие движки ESP-шаблонов не экранируют merge-поля автоматически, поэтому типографские кавычки и символы авторского права в именах пользователей требуют предварительного кодирования.
  • Документация и примеры кода: вставка примерного HTML-тега в Markdown-пост или фрагмент статического сайта требует кодирования скобок, чтобы рендерер воспринимал их как видимый текст.

Разобранный пример

Вставьте <script>alert('hi')</script> в поле ввода, установив режим «Кодировать», стиль «Именованный», область «Минимальная». На выходе получится &lt;script&gt;alert(&#39;hi&#39;)&lt;/script&gt;. Переключите стиль на «Числовой шестнадцатеричный» — тот же ввод даст &#x3C;script&#x3E;alert(&#x27;hi&#x27;)&#x3C;/script&#x3E;. Переведите режим в «Декодировать», вставьте закодированную строку обратно — и исходный тег восстановится.

FAQ

Что такое HTML-сущности?

HTML-сущности — это символьные ссылки, которые браузер при разборе страницы заменяет одиночными символами. Они существуют в трёх формах: именованные (например &amp; для &), десятичные числовые (&#38;) и шестнадцатеричные числовые (&#x26;). Пять зарезервированных HTML-символов (<, >, &, ", ') требуют кодирования при любом попадании текста в HTML. Остальные около 2225 именованных сущностей охватывают символы, диакритические знаки и греческие буквы, но необязательны при кодировке документа UTF-8.

Когда использовать именованные, а когда числовые сущности?

Используйте именованные сущности, когда хотите, чтобы исходный код читался легко (разработчик, видя &copy; в шаблоне, сразу понимает смысл). Применяйте числовые (десятичные или шестнадцатеричные), когда потребитель — старый или строгий: XML-парсеры, устаревшие почтовые клиенты и некоторые читалки лент распознают лишь небольшое подмножество именованных HTML5-сущностей, тогда как числовые понимают все. Шестнадцатеричный формат предпочтителен в контексте безопасности, поскольку соответствует нотации кодовых точек Unicode в спецификациях.

Декодирует ли инструмент шестнадцатеричные сущности вроде &?

Да. Декодер использует одно регулярное выражение, совпадающее со всеми тремя формами сущностей за один проход: &name;, &#NNN; и &#xHH;. Числовые совпадения разрешаются через String.fromCodePoint с основанием 10 или 16. Смешанный ввод (именованные и числовые в одной строке) декодируется корректно, а неизвестные имена остаются как литеральный текст — частичный ввод не теряет данных.

Безопасен ли инструмент для недоверенных данных?

Кодек работает только в браузере и не передаёт ввод куда-либо. Безопасность вывода для встраивания зависит от контекста. Кодирование сущностей покрывает контексты HTML-тела и значений атрибутов — это соответствует требованиям OWASP Rule #1. Для JavaScript-контекстов (обработчики событий, блоки `<script>`), CSS и URL требуются отдельные правила кодирования — одних сущностей там недостаточно. Для глубокой серверной защиты сочетайте с контекстно-осведомлённым шаблонизатором, таким как DOMPurify или встроенное автоэкранирование фреймворка.

Кодирование сущностей на стороне браузера стоит на границе между пользовательским вводом и отображаемым HTML. Локальное выполнение преобразования позволяет проверить, что именно выдал бы ваш фреймворк, не отправляя исходный текст сторонним инструментам.