Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Вставка без экранирования

Обычная вставка #{...} экранирует значение: заменяет <, >, & и кавычки на безопасные коды, чтобы текст оставался текстом. Иногда в переменной лежит готовый HTML, который должен стать разметкой. Для этого есть вставка без экранирования — !{...} и !=.

Готовый HTML в переменной

Пусть в build.js передаётся рекламная строка с тегом strong:

// build.js
const html = pug.renderFile("src/index.pug", {
  pretty: true,
  promo: "<strong>Скидка 10%</strong> на кофе до полудня",
});

Если вывести её обычной вставкой в src/index.pug:

p.promo #{promo}

теги появятся на странице как текст:

<p class="promo">&lt;strong&gt;Скидка 10%&lt;/strong&gt; на кофе до полудня</p>

Вставка через !{} и !=

Восклицательный знак отключает экранирование. Измените src/index.pug:

p.promo !{promo}
p.promo!= promo

Обе строки делают одно и то же: !{...} — вставка внутрь текста, != — всё содержимое тега. Теперь слова «Скидка 10%» выделены жирным:

<p class="promo"><strong>Скидка 10%</strong> на кофе до полудня</p>
<p class="promo"><strong>Скидка 10%</strong> на кофе до полудня</p>
ЗаписьЭкранируетГде писать
#{...}ДаВнутри текста
tag= ...ДаВсё содержимое тега
!{...}НетВнутри текста
tag!= ...НетВсё содержимое тега

Опасность: XSS

XSS (межсайтовый скриптинг) — атака, при которой злоумышленник отправляет на сайт текст с HTML-кодом, и этот код выполняется в браузерах других посетителей. Например, вместо отзыва о кофе кто-то пишет:

<img src=x onerror="alert('Взлом')">

Если отзыв приходит в шаблон в переменной review и выводится с экранированием:

p.review= review

посетители увидят безобидный текст:

<p class="review">&lt;img src=x onerror=&quot;alert('Взлом')&quot;&gt;</p>

А строка p.review!= review вставит отзыв как разметку:

<p class="review"><img src=x onerror="alert('Взлом')"></p>

Этот результат показан простым текстом, а не страницей: в браузере картинка не загрузится, и сработает onerror — выполнится чужой JavaScript. Вместо alert там может быть код, который крадёт данные посетителя.

Когда можно без экранирования

Вставляйте без экранирования только HTML, который написали вы сами или который получен из надёжного источника, например из ваших файлов Markdown, превращённых в HTML при сборке. Всё, что вводят посетители, — отзывы, имена, комментарии — выводите через = и #{...}.

Частая ошибка

Поставить != «на всякий случай», чтобы кавычки или амперсанды не превращались в коды. Экранированные символы браузер и так показывает правильно: &amp; на странице выглядит как &. Отключайте экранирование только там, где в переменной действительно нужный вам HTML.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.