React.js, как популярный фреймворк для создания пользовательских интерфейсов, сталкивается с множеством проблем безопасности. Они разделяются на уязвимости в самом фреймворке, практики разработки и управление зависимостями.
- Критические уязвимости в React Server Components (RSC)
- Проблемы базовой безопасности приложений
- Cross-Site Scripting (XSS) атаки
- Защита от CSRF (Cross-Site Request Forgery)
- Проблемы хранения аутентификационных данных
- Валидация и санитизация входных данных
- JSON Injection и eval()
- Проблемы безопасности зависимостей (Supply Chain)
- Уязвимости npm пакетов
- Prototype Pollution атаки
- Лучшие практики безопасности React приложений
- Итоговый чек-лист безопасности
Критические уязвимости в React Server Components (RSC)
В декабре 2025 года обнаружена критическая серия уязвимостей в React Server Components, которые требуют немедленного обновления.
CVE-2025-55182 (CVSS 10.0 — максимальный уровень серьезности) позволяет удаленное выполнение кода (RCE) на сервере через небезопасную десериализацию при обработке Flight протокола. Уязвимость не требует аутентификации и имеет надежность эксплуатации близкую к 100%. Активная эксплуатация в дикой природе начилась 5 декабря 2025 года, при этом атакующие развертывают крипто-майнеры, бэкдоры и украды облачных учетных данных.
- React: 19.0, 19.1, 19.2
- Next.js: 15.x, 16.x (App Router), Canary начиная с 14.3.0
Обновитесь до версий 19.0.3, 19.1.4, 19.2.3 как можно скорее.
Позже обнаружены дополнительные уязвимости:
- CVE-2025-55184 (CVSS 7.5) — отказ в обслуживании (DoS) через небезопасную десериализацию
- CVE-2025-67779 — еще один вектор DoS в результате неполного патча
Проблемы базовой безопасности приложений
Cross-Site Scripting (XSS) атаки
XSS остается одной из наиболее распространенных проблем в React приложениях.
dangerouslySetInnerHTML
Использование dangerouslySetInnerHTML обходит встроенные защиты React от XSS. React автоматически экранирует строковые значения, но dangerouslySetInnerHTML передает байпасс этого механизма.
Небезопасно:
javascript// Уязвимо для XSS
<div dangerouslySetInnerHTML={{__html: userInput}} />
Используйте библиотеки для санитизации, такие как DOMPurify:
javascriptimport DOMPurify from 'dompurify';
const sanitizedInput = DOMPurify.sanitize(userInput);
<div dangerouslySetInnerHTML={{__html: sanitizedInput}} />
Защита по умолчанию
React защищает от XSS автоматически при использовании данных связывания в фигурных скобках {}. Это рекомендуемый метод:
javascript// Безопасно — React экранирует значение
<div>{userInput}</div>
Защита от CSRF (Cross-Site Request Forgery)
CSRF атаки особенно опасны для операций изменения состояния (POST, PUT, DELETE).
- Сервер генерирует уникальный CSRF токен для каждой сессии пользователя
- Токен хранится в httpOnly cookie
- Frontend запрашивает токен перед изменяющимися операциями
- Токен отправляется в заголовке запроса (не в cookie, которое браузер отправляет автоматически)
javascript// Получение CSRF токена
const response = await fetch('/api/csrf-token');
const { csrfToken } = await response.json();
// Использование в защищенном запросе
fetch('/api/transfer', {
method: 'POST',
headers: {
'X-CSRF-Token': csrfToken,
'Content-Type': 'application/json'
},
body: JSON.stringify({ amount: 1000 })
});
- Установите
SameSiteдля cookies - Используйте подписанные токены
- Проверяйте origin/referrer заголовки
Проблемы хранения аутентификационных данных
Хранение JWT и других чувствительных токенов требует тщательного выбора подхода.
Преимущества:
- Защита от CSRF (токен не отправляется автоматически)
- Простоту реализации
Недостатки:
- Доступны любому JavaScript на странице, включая зловредные скрипты из скомпрометированных зависимостей
- Уязвимы для XSS атак
Преимущества:
- Недоступны для JavaScript
- Браузер отправляет автоматически
Недостатки:
- Уязвимы для CSRF (требует дополнительной защиты)
- CSRF токены должны быть в отдельном, доступном для чтения cookie
Хранить refresh token в httpOnly cookie, а access token в памяти или sessionStorage с коротким временем жизни. Это балансирует безопасность и удобство.
Валидация и санитизация входных данных
Необходимо применять многоуровневый подход к валидации:
- Валидация типов и формата — проверка что данные соответствуют ожидаемому типу
- Санитизация — удаление или экранирование потенциально опасных символов
- Использование библиотек — например Zod для валидации, DOMPurify для HTML
javascriptimport { z } from 'zod';
const userSchema = z.object({
email: z.string().email(),
name: z.string().min(2).max(50)
});
// Валидация перед использованием
const userData = userSchema.parse(input);
JSON Injection и eval()
Никогда не используйте eval() для парсинга JSON.
Уязвимо:
javascriptvar result = eval("(" + json_string + ")"); // ОПАСНО!
Безопасно:
javascriptvar result = JSON.parse(json_string); // Правильно
JSON.parse() — это простой текстовый парсер, который не выполняет код.
Проблемы безопасности зависимостей (Supply Chain)
Уязвимости npm пакетов
npm представляет критическую поверхность атаки для React проектов.
В сентябре 2025 года скомпрометировано 18 основных пакетов (chalk, debug, ansi-styles и др.), загружаемых 2.6 млрд раз в неделю. Атакующие внедрили код, переписывающий криптовалютные транзакции перед подписью.
В ноябре 2025 обнаружена критическая уязвимость CVE-2025-11953 в React Native Community CLI, позволяющая удаленное выполнение кода на машинах разработчиков.
- Используйте
package-lock.jsonпри установке (npm ciвместоnpm install) - Проверяйте версии хешей (избегайте SHA-1, используйте SHA-512)
- Регулярно сканируйте на известные уязвимости:
npm audit - Удаляйте неиспользуемые зависимости
- Закрепляйте (pin) версии в production, особенно для критических пакетов
Prototype Pollution атаки
Prototype Pollution позволяет атакующему добавлять или модифицировать свойства глобального Object.prototype.
Это может привести к RCE, если используется в сочетании с другими уязвимостями.
Пример уязвивого кода:
javascriptconst merge = (target, source) => {
for (let key in source) {
target[key] = source[key]; // Опасно если key == "__proto__"
}
return target;
};
Правильный подход:
javascriptconst merge = (target, source) => {
for (let key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
if (!key.startsWith('__') && key !== 'constructor' && key !== 'prototype') {
target[key] = source[key];
}
}
}
return target;
};
Лучшие практики безопасности React приложений
1. Используйте встроенные защиты React
Полагайтесь на автоматическое экранирование через JSX синтаксис {} вместо ручного манипулирования DOM.
2. Избегайте опасных URL паттернов
Не используйте динамические URL протоколы без валидации:
javascript// Уязвимо
<a href={userUrl}>Link</a>
// Правильно
const isValidUrl = (url) => {
try {
const u = new URL(url);
return ['http:', 'https:'].includes(u.protocol);
} catch {
return false;
}
};
<a href={isValidUrl(userUrl) ? userUrl : '#'}>Link</a>
3. Защита Server-Side Rendering (SSR)
При использовании SSR с dangerouslySetInnerHTML, всегда санитизируйте контент, даже если он поступает с сервера.
4. Настройка ESLint для безопасности
Используйте конфигурацию ESLint React Security для автоматического обнаружения уязвимостей:
bashnpm install --save-dev eslint-plugin-react eslint-plugin-security
5. Code Splitting и Lazy Loading
Загружайте компоненты по требованию для уменьшения поверхности атаки в начальном бандле:
javascriptconst Dashboard = React.lazy(() => import('./Dashboard'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<Dashboard />
</Suspense>
);
}
6. Content Security Policy (CSP)
Установите строгую CSP для защиты от XSS:
xml<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self' 'nonce-xyz123'">
7. Мониторинг и логирование безопасности
Логируйте отклоненные входные данные и подозрительную активность для раннего обнаружения атак.
Итоговый чек-лист безопасности
- Обновитесь до последних версий React (19.0.3+, 19.1.4+, 19.2.3+)
- Санитизируйте все пользовательские входные данные
- Используйте CSRF токены для операций изменения состояния
- Правильно храните аутентификационные токены (httpOnly cookies + CSRF защита)
- Регулярно проверяйте npm зависимости (
npm audit) - Избегайте
eval()иdangerouslySetInnerHTMLбез необходимости - Реализуйте Content Security Policy
- Используйте HTTPS для всех коммуникаций
- Проводите регулярные security code reviews
- Мониторьте и логируйте подозрительную активность
React обеспечивает базовую защиту от XSS через автоматическое экранирование, но разработчики должны дополнить это многоуровневым подходом к безопасности, учитывая тот факт, что фреймворк сам по себе уязвим для серьезных проблем, особенно в RSC компонентах.





