Основы безопасности клиентских приложений

Контекст безопасности в клиентских приложениях

Безопасность веб-приложений на стороне клиента имеет критическое значение, поскольку браузер является первым уровнем взаимодействия пользователя с приложением. Ошибки в обработке данных, уязвимости в рендеринге компонентов и недостаточная фильтрация пользовательского ввода могут привести к XSS (Cross-Site Scripting), CSRF (Cross-Site Request Forgery), утечкам данных и другим угрозам. Preact, как легковесный фреймворк, наследует многие принципы безопасности React, но требует внимательного подхода к интеграции с внешними библиотеками и API.

Управление вводом данных

Любой пользовательский ввод должен считаться потенциально опасным. Preact использует JSX для описания интерфейсов, что позволяет вставлять переменные напрямую в разметку. Важное правило: никогда не вставлять необработанные строки в DOM с помощью dangerouslySetInnerHTML без полной очистки содержимого. Для безопасного рендеринга текста рекомендуется:

import { h } from 'preact';

const SafeComponent = ({ userInput }) => (
    <div>{userInput}</div> // JSX автоматически экранирует спецсимволы
);

Использование dangerouslySetInnerHTML должно сопровождаться строгой очисткой через библиотеки вроде DOMPurify:

import DOMPurify from 'dompurify';

const SafeHTML = ({ html }) => (
    <div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(html) }} />
);

Защита от XSS

XSS-атаки возникают при внедрении вредоносного скрипта в приложение. В Preact большинство XSS-уязвимостей предотвращаются за счёт автоматического экранирования JSX. Однако при интеграции с внешними API, JSON-данными или сторонними виджетами следует:

  • Избегать динамического создания элементов с innerHTML.
  • Проверять данные на наличие скриптов и тегов <script>, <iframe>.
  • Использовать безопасные шаблонизаторы и утилиты для обработки HTML.

Контроль состояния приложения

Хранение чувствительных данных на клиенте требует осторожности. Preact не предоставляет встроенной системы безопасности для состояния, поэтому следует придерживаться правил:

  • Никогда не хранить токены аутентификации в localStorage или sessionStorage без шифрования.
  • Использовать httpOnly cookies для токенов, чтобы предотвратить доступ через JavaScript.
  • Ограничивать доступ к приватным маршрутам с использованием проверок на серверной стороне.

CSRF и безопасные запросы

CSRF-атаки эксплуатируют доверие браузера к сайту. В Preact-приложении защиту реализуют через:

  • Добавление CSRF-токена в заголовки fetch-запросов.
  • Использование безопасных методов HTTP (POST, PUT, DELETE) с проверкой на сервере.
  • Ограничение происхождения запросов через CORS с точечными настройками.

Пример безопасного fetch-запроса:

fetch('/api/data', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'X-CSRF-Token': csrfToken
    },
    body: JSON.stringify({ data: userData })
});

Валидация и фильтрация данных

Даже на клиенте необходимо фильтровать вводимые данные для улучшения UX и предотвращения ошибок. В Preact это достигается с помощью:

  • Контролируемых компонентов (controlled components) для форм.
  • Встроенной проверки типов через TypeScript или PropTypes.
  • Использования библиотек для валидации данных (yup, validator.js).
import { h } from 'preact';
import { useState } from 'preact/hooks';
import * as yup from 'yup';

const schema = yup.object().shape({
    email: yup.string().email().required()
});

const FormComponent = () => {
    const [email, setEmail] = useState('');

    const handleSubmit = async () => {
        try {
            await schema.validate({ email });
            console.log('Валидация успешна');
        } catch (err) {
            console.error('Ошибка валидации:', err);
        }
    };

    return (
        <form onSub mit={e => { e.preventDefault(); handleSubmit(); }}>
            <input value={email} onIn put={e => setEmail(e.target.value)} />
            <button type="submit">Отправить</button>
        </form>
    );
};

Безопасное использование сторонних библиотек

Preact совместим с большинством React-библиотек, но каждая внешняя зависимость может быть источником угроз. Необходимо:

  • Проверять версии и репутацию библиотек.
  • Избегать библиотек, которые напрямую манипулируют DOM.
  • Следить за обновлениями и патчами безопасности.

Настройка CSP и заголовков безопасности

Content Security Policy (CSP) ограничивает источники, с которых загружается контент. Для Preact-приложений рекомендуется:

  • Разрешать скрипты только с доверенных доменов.
  • Отключать выполнение inline-скриптов ('unsafe-inline').
  • Ограничивать загрузку стилей и изображений с неизвестных источников.

Пример CSP-заголовка на сервере:

Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' https://fonts.googleapis.com

Поддержка HTTPS и шифрование данных

Все соединения должны быть защищены TLS. Клиентское приложение должно:

  • Работать только по HTTPS.
  • Использовать безопасные cookie и заголовки Strict-Transport-Security.
  • Шифровать чувствительные данные перед отправкой на сервер при необходимости.

Мониторинг и аудит безопасности

Регулярная проверка клиентского кода помогает выявлять уязвимости:

  • Статический анализ с ESLint и плагинами безопасности.
  • Интеграция с SAST/DAST инструментами.
  • Логирование ошибок и подозрительных событий без утечки данных.

Безопасность Preact-приложений строится на сочетании корректной работы с JSX, строгой фильтрации данных, безопасного хранения состояния и внимательного использования сторонних библиотек. Соблюдение этих принципов снижает риск XSS, CSRF и других распространённых угроз веб-клиентам.