Навигация

Безопасность фронтенда: обзор угроз и защит

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

Содержание

  1. Почему фронтендеру нельзя игнорировать безопасность
  2. Карта угроз
  3. XSS — атака, которая не умирает
  4. CSRF — когда браузер становится оружием
  5. CSP — вторая линия обороны
  6. Секреты и аутентификация
  7. HTTP-заголовки и зависимости
  8. Философия защиты — глубокая защита и безопасность по умолчанию
  9. Чек-лист безопасности
  10. Ключевые тезисы для интервью
  11. Заключение
  12. Полезные ссылки

Почему фронтендеру нельзя игнорировать безопасность

Многие фронтенд-разработчики считают безопасность «заботой бэкенда». Это опасное заблуждение. В современном вебе фронтенд — это точка входа для пользователей, место, где обрабатываются данные форм, хранятся токены и рендерится пользовательский контент. И именно здесь происходит большинство атак.

Представьте, что ваше приложение — это банк. Бэкенд — это хранилище денег в подвале с бронированными дверями. Но фронтенд — это окно выдачи, через которое клиенты общаются с кассиром. Если окно не защищено, неважно, насколько крепки стены хранилища — грабитель может дотянуться до денег прямо через окно.

OWASP Top 10 включает несколько уязвимостей, которые напрямую связаны с фронтендом: инъекции (включая XSS), broken access control, security misconfiguration. Каждая из них может быть эксплуатирована через клиентскую часть приложения.


Карта угроз

УгрозаВекторОсновная защитаРазбор
XSSИнъекция кода через ввод пользователяЭкранирование, санитизация, CSPXSS: анатомия атаки
CSRFБраузер жертвы как оружиеSameSite, CSRF-токены, OriginCSRF: механика атаки
Утечка секретовNEXT_PUBLIC_, runtimeConfig, gitСерверный прокси, vaults, hooksУправление секретами
Слабая аутентификацияКросс-сайтовые утечки токеновHttpOnly cookies, OAuth/PKCE, RBACАутентификация и авторизация
Отсутствие заголовковClickjacking, downgrade, утечка URLSecurity-заголовки, CSPHTTP-заголовки безопасности
Supply chainВредоносные пакеты, typosquattingLock-файлы, npm audit, SBOMЗависимости и supply chain
Процессы и аудитCompliance, incident responseSecure SDLC, access reviewsSOC2 и CASA

XSS — атака, которая не умирает

XSS (Cross-Site Scripting) — это внедрение вредоносного JavaScript-кода в страницу, которую просматривает жертва. Существует с 1996 года и остаётся одной из самых распространённых уязвимостей, потому что каждый раз, когда приложение берёт данные от пользователя и вставляет их в HTML, создаётся потенциальная дыра.

Три основных типа:

  • Отражённый (Reflected) — код приходит в URL и «отражается» от сервера в ответе.
  • Хранимый (Stored) — код сохраняется в базе и показывается всем пользователям. Самый опасный тип.
  • DOM-based — код выполняется на клиенте через манипуляции с DOM, без участия сервера.

React и Vue автоматически экранируют значения в JSX/интерполяциях, но защита заканчивается там, где разработчик обходит её вручную: dangerouslySetInnerHTML и v-html, javascript: URL в атрибутах, прямой доступ к DOM через refs, несанитизированные third-party библиотеки.

Глубокий разбор: XSS: анатомия атаки и методы защиты.


CSRF — когда браузер становится оружием

CSRF (Cross-Site Request Forgery) — атака, при которой злоумышленник заставляет браузер жертвы выполнить нежелательный запрос к авторизованному сайту. Злоумышленник не взламывает сервер — он использует легитимный браузер пользователя как оружие: браузер автоматически прикрепляет cookies к запросам на домен, независимо от того, какой сайт инициировал запрос.

Три линии защиты, которые дополняют друг друга:

  1. CSRF-токены — сервер генерирует уникальный токен, злоумышленник не может его узнать из-за Same-Origin Policy.
  2. SameSite cookies — браузер не отправляет cookie при cross-site запросах; Lax — компромисс, Strict — максимальная защита.
  3. Проверка Origin/Referer — сервер проверяет, откуда пришёл запрос; дополнительный слой, а не замена токенов.

CSRF-защита нужна даже в эпоху JSON API: злоумышленник может отправить JSON-запрос через fetch с credentials: "include".

Глубокий разбор: CSRF: механика атаки и линии защиты.


CSP — вторая линия обороны

Content Security Policy (CSP) — HTTP-заголовок, который говорит браузеру, откуда разрешено загружать скрипты, стили, изображения и другие ресурсы. CSP не заменяет экранирование, а работает как вторая линия обороны: даже если XSS-уязвимость существует, политика блокирует выполнение вредоносного кода.

Ключевые концепции:

  • default-src 'self' задаёт базу, от которой отталкиваются остальные директивы;
  • 'unsafe-inline' в script-src сводит защиту на нет — вместо него используют nonce или hash;
  • strict-dynamic упрощает работу с бандлерами, не требуя жёсткого списка источников;
  • Content-Security-Policy-Report-Only позволяет тестировать политику без блокировки;
  • frame-ancestors 'none' защищает от clickjacking.

Глубокий разбор: CSP: директивы и практика.


Секреты и аутентификация

Секреты

Фундаментальное правило веба: всё, что отправляется в браузер, может быть прочитано. Переменные с префиксом NEXT_PUBLIC_ (и аналогами VITE_, NUXT_PUBLIC_) встраиваются в клиентский бандл на этапе сборки. Секретные ключи должны использоваться только в серверном коде через серверный прокси, а в production — через хранилища секретов (Vault, AWS Secrets Manager, Doppler) с ротацией и аудитом доступа. Защита .env от git — через .gitignore и pre-commit hooks (gitleaks).

Глубокий разбор: Управление секретами во фронтенде.

Аутентификация и авторизация

Аутентификация отвечает на вопрос «кто ты?», авторизация — «что тебе можно?». Для SPA важно понимать компромиссы между сессиями и JWT, пару access + refresh token, OAuth 2.0 и OIDC с PKCE, и почему хранение токенов в localStorage опаснее HttpOnly cookies. Контроль доступа строится на RBAC (роли) и ABAC (атрибуты). Клиентская проверка авторизации — лишь адаптация UI, серверная валидация обязательна на каждом уровне.

Глубокий разбор: Аутентификация и авторизация во фронтенде.


HTTP-заголовки и зависимости

HTTP-заголовки

Security-заголовки закрывают целые классы атак без изменений в бизнес-логике: HSTS блокирует downgrade на HTTP, X-Frame-Options — clickjacking, X-Content-Type-Options: nosniff — MIME-sniffing, Referrer-Policy — утечку URL, COOP/COEP — cross-origin атаки, Permissions-Policy — ненужные браузерные API.

Глубокий разбор: HTTP-заголовки безопасности.

Supply chain

Современный проект имеет сотни транзитивных зависимостей, каждая из которых — чужой код, выполняемый в вашем приложении. Инциденты event-stream, ua-parser-js, colors и xz utils показали, что угроза реальна. Защита: коммитить lock-файлы, запускать npm audit в CI, использовать Snyk/Socket, составлять SBOM и проверять provenance пакетов.

Глубокий разбор: Безопасность зависимостей и supply chain.

Compliance и аудит

Для SOC2 и CASA фронтендеру важно понимать, какие controls касаются его кода, как формализуются изменения в production, из каких фаз состоит incident response и как подготовиться к penetration test.

Глубокий разбор: SOC2 и CASA для фронтенд-разработчика.


Философия защиты — глубокая защита и безопасность по умолчанию

Принцип глубокой защиты (Defense in Depth)

Не полагайтесь на одну линию защиты. Каждая защита может быть обойдена — важно, чтобы за ней была другая.

Слой 1: Middleware — проверка авторизации
    ↓ (если обойдён)
Слой 2: Server Component — проверка прав
    ↓ (если обойдён)
Слой 3: Server Action — валидация данных
    ↓ (если обойдена)
Слой 4: Database — constraints и проверки
    ↓ (если обойдены)
Слой 5: CSP — блокировка вредоносного кода

Если злоумышленник обойдёт middleware (отправив запрос напрямую), его остановит Server Action. Если обойдёт Server Action (подделав сессию), его остановит проверка прав в базе данных. Если даже он вставит вредоносный скрипт, его заблокирует CSP.

Принцип наименьших привилегий

Каждый компонент, API-эндпоинт и Server Action должны иметь минимально необходимые права. Если функция может только читать данные, она не должна иметь права на запись. Если пользователь — обычный пользователь, он не должен иметь права администратора.

Безопасность по умолчанию

Компоненты и функции должны быть безопасными по умолчанию — без необходимости явно включать защиту. Разработчик должен приложить усилия, чтобы сделать что-то опасное, а не чтобы сделать что-то безопасное.

// ✅ Компонент безопасен по умолчанию
function ExternalLink({ href, children }) {
  return (
    <a href={href} rel="noopener noreferrer" target="_blank">
      {children}
    </a>
  );
}

rel="noopener noreferrer" предотвращает tabnabbing-атаку, и разработчик не должен помнить об этом — компонент уже безопасен.


Чек-лист безопасности

Перед деплоем

  • Обновлены React, Next.js и все зависимости
  • Проверено npm audit / pnpm audit
  • Секреты не в клиентском бандле (проверить через NEXT_PUBLIC_)
  • Настроены HTTP-заголовки безопасности
  • Настроен CSP (хотя бы в report-only режиме)
  • Server Actions валидируют входные данные
  • Проверка авторизации во всех защищённых маршрутах и действиях
  • CSRF-защита для критических операций
  • Rate limiting для публичных API
  • .env файлы в .gitignore
  • Cookie с флагами httpOnly, secure, sameSite
  • Lock-файлы закоммичены в репозиторий

Регулярно

  • Аудит зависимостей (еженедельно/ежемесячно)
  • Ротация секретов (ежеквартально)
  • Проверка CSP-отчётов
  • Penetration testing (для критических приложений)
  • Review зависимостей перед установкой новых пакетов

Антипаттерны — чего никогда не делать

1. Хранение секретов в клиентском коде. Если ключ попадает в бандл — он скомпрометирован. Используйте серверные прокси.

2. Игнорирование валидации. Клиентские данные — это хаос. Валидируйте всё на сервере, даже если есть валидация на клиенте.

3. Хранение токенов в localStorage. XSS может украсть localStorage. Используйте HttpOnly cookies.

4. Отсутствие rate limiting. Без rate limiting ваше API уязвимо для spam и brute-force атак.

5. Доверие параметрам URL. URL контролирует пользователь. Валидируйте все параметры маршрутов.

6. Передача лишних данных клиенту. Если клиенту не нужно поле passwordHash — не передавайте его, даже если рендерите только name.


Ключевые тезисы для интервью

  • Безопасность фронтенда — не «забота бэкенда»: XSS, CSRF, кража секретов и Open Redirect эксплуатируются именно через клиент; defense in depth — middleware, серверная проверка, БД-constraints и CSP работают в связке.
  • XSS бывает трёх типов — отражённый, хранимый и DOM-based; React экранирует значения в JSX, но dangerouslySetInnerHTML, javascript: URL и прямой доступ к DOM обходят защиту; CSP — вторая линия обороны, nonce-based CSP со strict-dynamic даёт наиболее строгую защиту.
  • CSRF работает потому, что браузер автоматически прикрепляет cookies к cross-site запросам; защита строится на CSRF-токенах, SameSite cookies и проверке Origin/Referer.
  • Server Actions выполняются на сервере, но вызываются с клиента — валидация входа (Zod), проверка авторизации и rate limiting обязательны в каждом действии.
  • Переменные с префиксом NEXT_PUBLIC_ встраиваются в клиентский бандл; секретные ключи — только в серверном коде через прокси; аутентификация отвечает «кто вы», авторизация — «что вам можно», проверять нужно на middleware, Server Component и Server Action.
  • HTTP-заголовки (X-Frame-Options, HSTS, Referrer-Policy, Permissions-Policy) закрывают класс атак с минимальными усилиями; lock-файлы и npm audit в CI защищают от supply chain атак.

Заключение

Безопасность фронтенда — это не набор изолированных проверок, а системный подход. React экранирует JSX, но dangerouslySetInnerHTML открывает XSS. SameSite=Lax защищает от CSRF в большинстве случаев, но токены нужны для критических операций. Server Actions удобны, но требуют явной валидации и авторизации. CSP закрывает вредоносные скрипты, HTTP-заголовки — clickjacking, HSTS — downgrade-атаки, аудит зависимостей — supply chain. Работайте по принципу defense in depth: каждая защита может быть обойдена, но за ней должна быть следующая. И помните главное правило — никогда не доверяйте клиенту.

Полезные ссылки