(low) weightProfiles.ts/useWeightProfiles: admin-токен лишний в queryKey React Query #1489

Closed
opened 2026-06-15 05:58:37 +00:00 by bot-backend · 0 comments
Collaborator

Severity: low · Категория: security · Файл: frontend/src/lib/api/weightProfiles.ts:101-113

weightProfiles.ts:103 — queryKey хука useWeightProfiles содержит сам adminToken: ['weight-profiles', userId, adminToken]. adminToken — реальный админ-секрет (legacy/site-finder/page.tsx:135 читает его из localStorage('admin_token')), который в норме передаётся ТОЛЬКО как заголовок X-Admin-Token (profilesHeaders, weightProfiles.ts:94-95). Помещение секрета в идентификатор кэша — антипаттерн. Импакт ограничен: в проекте НЕ подключены ни ReactQueryDevtools, ни persistQueryClient/createSyncStoragePersister (проверено grep по frontend) — токен остаётся только в in-memory QueryCache и на диск/в localStorage не сериализуется, поэтому реального утечки-вектора сверх того, что уже даёт доступ к localStorage, нет. Реальный вред — cache-bloat/осиротевшие записи при ротации токена и стейл-стейт, т.к. новый токен порождает новый ключ. Функционально adminToken в ключе не нужен: инвалидация в useCreateProfile/useUpdateProfile/useDeleteProfile использует префикс ['weight-profiles', userId] и матчится partial-match. Чинить: queryKey: ['weight-profiles', userId]. Severity понижена с medium до low (нет persister/devtools, секрет не покидает память).

Почему баг: Ключи React Query видны в React Query DevTools и сериализуются любым cache-persister'ом (persistQueryClient/localStorage). Токен из заголовка не должен утекать в идентификатор кэша. Доп. эффект: при ротации/смене токена старый ключ остаётся «висеть» в кэше осиротевшей записью (cache bloat / стейл-стейт), т.к. новый токен порождает новый ключ. Инвалидация в мутациях использует префикс ["weight-profiles", userId] и matchится верно (partial-match), так что adminToken в ключе не нужен функционально — только вредит. Достаточно queryKey: ["weight-profiles", userId].

Как чинить: Убрать adminToken из queryKey: queryKey: ["weight-profiles", userId]. Токен и так уходит в заголовке через profilesHeaders; в ключе кэша секрету не место.


deep-audit «армия ботов 2» · verify+harden, confidence 0.8 · unit U109

**Severity:** low · **Категория:** security · **Файл:** `frontend/src/lib/api/weightProfiles.ts:101-113` weightProfiles.ts:103 — queryKey хука useWeightProfiles содержит сам adminToken: ['weight-profiles', userId, adminToken]. adminToken — реальный админ-секрет (legacy/site-finder/page.tsx:135 читает его из localStorage('admin_token')), который в норме передаётся ТОЛЬКО как заголовок X-Admin-Token (profilesHeaders, weightProfiles.ts:94-95). Помещение секрета в идентификатор кэша — антипаттерн. Импакт ограничен: в проекте НЕ подключены ни ReactQueryDevtools, ни persistQueryClient/createSyncStoragePersister (проверено grep по frontend) — токен остаётся только в in-memory QueryCache и на диск/в localStorage не сериализуется, поэтому реального утечки-вектора сверх того, что уже даёт доступ к localStorage, нет. Реальный вред — cache-bloat/осиротевшие записи при ротации токена и стейл-стейт, т.к. новый токен порождает новый ключ. Функционально adminToken в ключе не нужен: инвалидация в useCreateProfile/useUpdateProfile/useDeleteProfile использует префикс ['weight-profiles', userId] и матчится partial-match. Чинить: queryKey: ['weight-profiles', userId]. Severity понижена с medium до low (нет persister/devtools, секрет не покидает память). **Почему баг:** Ключи React Query видны в React Query DevTools и сериализуются любым cache-persister'ом (persistQueryClient/localStorage). Токен из заголовка не должен утекать в идентификатор кэша. Доп. эффект: при ротации/смене токена старый ключ остаётся «висеть» в кэше осиротевшей записью (cache bloat / стейл-стейт), т.к. новый токен порождает новый ключ. Инвалидация в мутациях использует префикс ["weight-profiles", userId] и matchится верно (partial-match), так что adminToken в ключе не нужен функционально — только вредит. Достаточно queryKey: ["weight-profiles", userId]. **Как чинить:** Убрать adminToken из queryKey: `queryKey: ["weight-profiles", userId]`. Токен и так уходит в заголовке через profilesHeaders; в ключе кэша секрету не место. --- <sub>deep-audit «армия ботов 2» · verify+harden, confidence 0.8 · unit U109</sub>
bot-backend added the
week ревью 1
label 2026-06-15 05:58:37 +00:00
bot-backend added the
scope/frontend
label 2026-06-15 11:02:12 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#1489
No description provided.