Cross-Site Scripting (XSS) представляет собой тип уязвимости, при котором злоумышленник внедряет вредоносный скрипт в веб-приложение. В контексте Stencil, как и других фреймворков на JavaScript, защита от XSS особенно важна, так как компонентная архитектура активно работает с DOM и часто использует динамическое рендеринг-содержимое. XSS-атаки могут привести к краже сессий, изменению данных на клиенте или внедрению вредоносного кода.
Stencil использует JSX для описания компонентов, что обеспечивает встроенную защиту от XSS при стандартной вставке данных. Все выражения в JSX, такие как:
render() {
return <div>{this.userInput}</div>;
}
автоматически экранируются. Это значит, что
специальные символы HTML (<, >,
&, ", ') преобразуются в
безопасные сущности, предотвращая выполнение произвольного
JavaScript-кода.
Использование innerHTML или
dangerouslySetInnerHTML обходят автоматическую экранизацию,
что делает их потенциально опасными:
render() {
return <div innerHTML={this.userInput}></div>;
}
Чтобы безопасно работать с динамическим HTML:
Пример безопасного использования DOMPurify:
import DOMPurify from 'dompurify';
render() {
const safeHTML = DOMPurify.sanitize(this.userInput);
return <div innerHTML={safeHTML}></div>;
}
Санитизация — процесс удаления или преобразования небезопасных элементов в данных, а валидация — проверка соответствия данных допустимым форматом. В Stencil рекомендуется:
Пример валидации строкового пропса:
@Component({
tag: 'safe-message',
shadow: true
})
export class SafeMessage {
@Prop() text: string;
render() {
const sanitizedText = this.text.replace(/</g, '<').replace(/>/g, '>');
return <p>{sanitizedText}</p>;
}
}
Использование Shadow DOM в Stencil создаёт изолированное дерево DOM для компонентов, что затрудняет внедрение скриптов извне, но не заменяет полноценную санитизацию. Любой контент, передаваемый через свойства или атрибуты, должен быть обработан и экранирован, так как Shadow DOM защищает только от внешнего CSS и DOM-перезаписи, но не предотвращает выполнение скриптов, вставленных внутрь компонента.
innerHTML, когда это
возможно.render() {
return <span>{this.dynamicText}</span>;
}
render() {
const safeContent = DOMPurify.sanitize(this.htmlContent);
return <div innerHTML={safeContent}></div>;
}
render() {
const safeUrl = encodeURI(this.url);
return <a href={safeUrl}>Ссылка</a>;
}
Эти практики минимизируют риск XSS и обеспечивают высокий уровень безопасности в приложениях на Stencil.