[CL-SEC-Q2] admin.users.routes: admin-secret step-up на money/destructive/bulk #792

Merged
andrei merged 1 commit from feature/claude-sec-q2-admin-users-secret-gate into master 2026-06-20 16:00:04 +00:00
Owner

Что сделано

Добавлен step-up admin-secret-фактор requireAdminSecretVerified на 3 маршрута в api/src/routes/admin.users.routes.ts:

  • POST /users/:id/adjust-balance — напрямую мутирует user.balance (money path);
  • DELETE /users/:id — деструктивное удаление;
  • POST /users/bulk — массовый lock/unlock/approve_kyc/reject_kyc (до 50 юзеров).

Новый структурный тест admin.users.routes.test.ts (обход router.stack) гарантирует наличие gate на этих маршрутах.

Зачем

MEDIUM-finding квартального аудита (SEC-Q2-2026), категория A01 Broken Access Control. Эти маршруты были защищены только adminApiKeyOrJwt (auth+role+2FA-enrollment) + rate-limit, но без step-up secret-фактора, который sibling money-роутеры (payments, erc3643, infra, synthetics, managed-invest, open-banking) уже требуют. admin.users.routes его даже не импортировал.

Тот же класс, что и CRITICAL-фикс money-роутов в admin.payments.routes (PR #781). Gate применяется per-router (opt-in), глобально на /admin его нет — поэтому пропуск был реальным.

AUDIT: SEC-Q2-2026.

План тестирования

  • TDD: новый тест RED (3/3 fail — gate отсутствовал) -> GREEN (3/3 pass).
  • vitest run src/routes — 282/282.
  • tsc --noEmit чисто; eslint 0 ошибок.
  • pre-push: 189 integration tests + app build зелёные.
  • Проверил: интеграционных тестов, дёргающих эти endpoint без секрета, нет — регрессий 403 не будет.

Где могу ошибаться

  • Не добавил gate на PATCH /users/:id (updateUser) — finding его не называл; updateUser может менять чувствительные поля, но расширение скоупа рискует сломать admin-UX. Если ревью считает нужным — добавлю.
  • /users/bulk теперь требует секрет — если admin-фронт не пробрасывает x-admin-secret на bulk-операции, UX потребует verify-secret шага (как уже на payments).
## Что сделано Добавлен step-up admin-secret-фактор `requireAdminSecretVerified` на 3 маршрута в `api/src/routes/admin.users.routes.ts`: - `POST /users/:id/adjust-balance` — напрямую мутирует `user.balance` (money path); - `DELETE /users/:id` — деструктивное удаление; - `POST /users/bulk` — массовый lock/unlock/approve_kyc/reject_kyc (до 50 юзеров). Новый структурный тест `admin.users.routes.test.ts` (обход `router.stack`) гарантирует наличие gate на этих маршрутах. ## Зачем MEDIUM-finding квартального аудита (SEC-Q2-2026), категория A01 Broken Access Control. Эти маршруты были защищены только `adminApiKeyOrJwt` (auth+role+2FA-enrollment) + rate-limit, но **без** step-up secret-фактора, который sibling money-роутеры (`payments`, `erc3643`, `infra`, `synthetics`, `managed-invest`, `open-banking`) уже требуют. `admin.users.routes` его даже не импортировал. Тот же класс, что и CRITICAL-фикс money-роутов в `admin.payments.routes` (PR #781). Gate применяется per-router (opt-in), глобально на `/admin` его нет — поэтому пропуск был реальным. AUDIT: SEC-Q2-2026. ## План тестирования - TDD: новый тест RED (3/3 fail — gate отсутствовал) -> GREEN (3/3 pass). - `vitest run src/routes` — 282/282. - `tsc --noEmit` чисто; `eslint` 0 ошибок. - pre-push: 189 integration tests + app build зелёные. - Проверил: интеграционных тестов, дёргающих эти endpoint без секрета, нет — регрессий 403 не будет. ## Где могу ошибаться - Не добавил gate на `PATCH /users/:id` (updateUser) — finding его не называл; updateUser может менять чувствительные поля, но расширение скоупа рискует сломать admin-UX. Если ревью считает нужным — добавлю. - `/users/bulk` теперь требует секрет — если admin-фронт не пробрасывает `x-admin-secret` на bulk-операции, UX потребует verify-secret шага (как уже на payments).
[CL-SEC-Q2] admin.users.routes: admin-secret step-up на money/destructive/bulk
All checks were successful
CI / Contracts (pull_request) Successful in 1m49s
CI / API (pull_request) Successful in 11m58s
CI / Python SDK (pull_request) Successful in 25s
CI / Secrets Scan (pull_request) Successful in 21s
CI / Telegram Mini App (pull_request) Successful in 1m17s
PR Janitor / janitor (pull_request) Successful in 8s
CI / Prisma Migrate Gate (pull_request) Successful in 1m25s
CI / App (pull_request) Successful in 13m19s
ff7e7e1071
AUDIT: SEC-Q2-2026 — MEDIUM hardening sweep (broken-access-control A01).

Что:
adjust-balance (мутирует user.balance — money path), DELETE /users/:id
(деструктивно) и /users/bulk (массовый lock/unlock/approve_kyc/reject_kyc)
были защищены только admin-auth (adminApiKeyOrJwt) + rate-limit, без
step-up secret-фактора requireAdminSecretVerified. Sibling money-роутеры
(payments, erc3643, infra, synthetics, managed-invest, open-banking) этот
gate уже требуют — admin.users им не пользовался (даже не импортировал).

Добавлен requireAdminSecretVerified в эти 3 маршрута. Остальные user-роуты
(GET-список/статы/PATCH/partner-applications) не затронуты — finding точечный.

Тесты: новый структурный тест admin.users.routes.test.ts (обход router.stack)
TDD RED->GREEN; 282/282 routes-suite зелёные; tsc + eslint чисто.
forgejo-actions scheduled this pull request to auto merge when all checks succeed 2026-06-20 15:41:47 +00:00
andrei merged commit 3261b0a2b3 into master 2026-06-20 16:00:04 +00:00
andrei deleted branch feature/claude-sec-q2-admin-users-secret-gate 2026-06-20 16:00:09 +00:00
Sign in to join this conversation.
No reviewers
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
europa-tech-srl/europatech!792
No description provided.