Ответ
- Экранирование (escaping) – преобразование спецсимволов в HTML-сущности (например,
<→<).
Пример:
const escaped = str.replace(/</g, '<').replace(/>/g, '>');
- Использование textContent вместо innerHTML – предотвращает интерпретацию HTML/JS.
element.textContent = userInput; // безопасно
- Content Security Policy (CSP) – HTTP-заголовок, ограничивающий источники скриптов, стилей и т.д.
Пример заголовка:
Content-Security-Policy: default-src 'self'
- Библиотеки для санитизации – например, DOMPurify:
const clean = DOMPurify.sanitize(userInput);
-
HttpOnly и Secure флаги для кук – защищает от кражи кук через JS.
-
Валидация и ограничение ввода – например, разрешать только определенные символы.
Для React/Vue/Angular: фреймворки автоматически экранируют данные в шаблонах, но важно избегать dangerouslySetInnerHTML (React) или v-html (Vue) без санитизации.
Ответ 18+ 🔞
Ну ты смотри, какие умные головы придумали, чтобы нас, разработчиков, не выебали на ровном месте! XSS — это ж как геморрой, только в коде. Сидит где-то в твоём приложении и ждёт, когда ты расслабишься, чтобы впендюрить свой скрипт. А потом — бац! — и у тебя все куки уплыли к какому-то пидарасу шерстяному. Так что слушай сюда, как от этого чуда обороняться.
Первое, что надо усвоить — экранирование. Это когда ты все эти ебучие угловые скобки и амперсанды превращаешь в безобидные буковки. Типа < становится <. Делается это просто, но мозг выносит, если делать вручную.
const escaped = str.replace(/</g, '<').replace(/>/g, '>');
Но реально, кто ж так будет делать? Только мазохист. Поэтому второе правило — не лезь в innerHTML с грязными данными. Есть же textContent! Он не пытается быть умным и просто вставляет текст как есть, не парся его как HTML.
element.textContent = userInput; // вот так безопасно, блядь
Дальше идёт Content Security Policy (CSP). Это такая тяжёлая артиллерия. Ты говоришь браузеру: "Слушай, дружок, скрипты грузи только отсюда, стили — оттуда, а всё остальное — нахуй". В заголовках это выглядит как магия:
Content-Security-Policy: default-src 'self'
Это значит — всё только со своего сервака. Попробуй впендюрить скрипт с левого домена — браузер его посылает на три весёлые буквы.
Если уж совсем припёрло и надо вставить HTML, который тебе прислал пользователь (ну, там, rich-text редактор), то используй библиотеки для санитизации. DOMPurify, например. Он как хороший сантехник — вычищает всё дерьмо, оставляя только безопасные теги.
const clean = DOMPurify.sanitize(userInput); // вот теперь можно и в innerHTML
Про куки не забудь! Ставь им флаги HttpOnly и Secure. Первый не даёт JavaScript'у до них достучаться, второй — чтобы летали только по HTTPS. Красть их станет в разы сложнее, хоть и не невозможно.
Ну и, само собой, валидация. Если поле для номера телефона — пусть там будут только цифры, плюс и скобки. Не надо давать пользователям вводить всякую хуйню, они же её потом и отправят, распиздяи.
Для фреймворков (React, Vue, Angular) — там обычно всё заэкранировано автоматически. Но есть лазейки! В React — dangerouslySetInnerHTML, в Vue — v-html. Это прям кричащие названия, ёпта! "Опасно установить внутренний HTML" — ну как будто тебя предупреждают: "Чувак, не надо, там пиздец будет". Если уж юзаешь — пропусти данные через санитизатор, будь не мудаком.
Короче, суть в чём: не доверяй никому. Ни пользователю, ни себе в пятницу вечером. Всегда предполагай, что входящие данные — это бомба, и обезвреживай их, пока не стало поздно. А то будет как в том анекдоте: "Ваш сайт взломали". — "И что сделали?" — "Ничего, просто на главной странице теперь летает dickbutt". Волнение ебать!