Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Наскільки безпечні шаблони Vue і коли v-html відкриває XSS?

За замовчуванням Vue екранує дані: інтерполяція {{ }} і прив'язки атрибутів вставляють значення як текст, а не як HTML.

<p>{{ comment.body }}</p>               <!-- <script> покажеться як текст -->
<a :title="comment.author">...</a>      <!-- значення атрибута екрановано -->

Де захист закінчується:

1. v-html вставляє рядок як HTML:

<div v-html="comment.body"></div>   <!-- XSS, якщо body від користувача -->

Для контенту від користувачів - лише після санітизації (DOMPurify на клієнті чи HTML Purifier на сервері), а краще - зберігати Markdown і рендерити безпечним рендерером з білим списком тегів.

2. URL у атрибутах: екранування не захищає від схеми javascript::

<a :href="user.website">Сайт</a>   <!-- javascript:alert(1) виконається при кліку -->

Перевіряйте протокол (http:/https:) перед виведенням посилань з даних користувача.

3. :style з даних користувача - можливі атаки через CSS (підміна інтерфейсу, витік через url()).

4. Шаблон з даних користувача. Найнебезпечніший випадок - компіляція рядка, що містить ввід користувача, як шаблону Vue:

createApp({ template: `<div>${userInput}</div>` });   // виконання довільних виразів

Шаблон Vue - це код. Будь-що, що компілюється як шаблон, має повністю контролюватися розробником.

5. Серверний рендер + Vue в браузері (Blade, Laravel). Якщо Vue монтується на розмітку, яку сервер згенерував з даними користувача (in-DOM шаблон), то {{ }} у даних користувача Vue виконає як вираз. Користувач пише коментар {{ constructor.constructor('alert(1)')() }} - Blade екранує HTML, але не фігурні дужки, і Vue їх обчислить. Захист: не монтувати Vue на області з користувацьким вмістом, позначати такі ділянки v-pre, передавати дані через props/JSON, а не через розмітку.

Вирази шаблонів у «пісочниці»: у шаблоні доступний лише обмежений набір глобальних об'єктів (Math, Date тощо), а не window. Але це не межа безпеки - через ланцюжок конструкторів можна дістатися до Function, тому вимога «шаблони лише від розробника» лишається.

Що ще: Content Security Policy знижує наслідки XSS. Повна збірка Vue з компілятором шаблонів у браузері потребує unsafe-eval; збірка лише з runtime (шаблони скомпільовані Vite) - ні.

Докладніше в документації: Безпека

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання