[CL-SEC] аудит Q2: admin-secret + 2FA гейты на money-маршрутах (force-expire/refund/reject) #781

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

Что сделано

Квартальный security-аудит (2026-Q2, OWASP). Закрыты 2 CRITICAL по admin money-маршрутам:

  1. requireAdminSecretVerified добавлен на POST /payments/:id/force-expire (освобождает зарезервированные доли) и /payments/:id/refund (возврат средств) — раньше gate был только у соседних force-complete/change-status. Regression-тест admin.payments.routes.test.ts.
  2. 2FA-порог на POST /payouts/:id/reject — отклонение кредитует EUR-баланс (income-payout/admin-operations.ts:144), но не требовало 2FA ни при какой сумме (в отличие от approvePayout). Добавлен тот же порог PAYOUT_2FA_THRESHOLD_EUR + twoFactorCode в rejectPayoutSchema. Тесты в admin.payouts.controller.test.ts.

Отчёт: docs/security/audit-2026-Q2.md.

Зачем

Скомпрометированная admin-сессия без admin-secret/TOTP могла освобождать доли, возвращать средства и начислять баланс через reject. Асимметрия защиты на путях с реальными деньгами.

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

  • vitest admin.payments.routes (4/4), admin.payouts.controller (17/17), schemas coverage (5/5).
  • tsc --noEmit clean, eslint --max-warnings 0 clean.
  • pre-push: 189 integration tests passed.

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

  • Финансовый путь (Rule 103.1) → merge требует sign-off CEO.
  • Остальные 3 CRITICAL (#3 _skipOtp service-layer, #4 KYC TOCTOU, #5 NOWPayments ordering) — это multi-file рефакторы с regression-риском на cron/webhook путях; вынесены в follow-up PR после merge этого, чтобы diff оставался review-able. Список в отчёте.

Access review (Task 2) — выполнено отдельно на prod

0 inactive ADMIN (3/3 active, никого не удалял), 1 unused API key revoked (ek_live_987f), PM2 env audit-даты → 2026-06-20.

## Что сделано Квартальный security-аудит (2026-Q2, OWASP). Закрыты 2 CRITICAL по admin money-маршрутам: 1. `requireAdminSecretVerified` добавлен на `POST /payments/:id/force-expire` (освобождает зарезервированные доли) и `/payments/:id/refund` (возврат средств) — раньше gate был только у соседних force-complete/change-status. Regression-тест `admin.payments.routes.test.ts`. 2. 2FA-порог на `POST /payouts/:id/reject` — отклонение кредитует EUR-баланс (`income-payout/admin-operations.ts:144`), но не требовало 2FA ни при какой сумме (в отличие от approvePayout). Добавлен тот же порог `PAYOUT_2FA_THRESHOLD_EUR` + `twoFactorCode` в `rejectPayoutSchema`. Тесты в `admin.payouts.controller.test.ts`. Отчёт: `docs/security/audit-2026-Q2.md`. ## Зачем Скомпрометированная admin-сессия без admin-secret/TOTP могла освобождать доли, возвращать средства и начислять баланс через reject. Асимметрия защиты на путях с реальными деньгами. ## План тестирования - `vitest` admin.payments.routes (4/4), admin.payouts.controller (17/17), schemas coverage (5/5). - `tsc --noEmit` clean, `eslint --max-warnings 0` clean. - pre-push: 189 integration tests passed. ## Где могу ошибаться - Финансовый путь (Rule 103.1) → merge требует sign-off CEO. - Остальные 3 CRITICAL (#3 `_skipOtp` service-layer, #4 KYC TOCTOU, #5 NOWPayments ordering) — это multi-file рефакторы с regression-риском на cron/webhook путях; вынесены в follow-up PR после merge этого, чтобы diff оставался review-able. Список в отчёте. ## Access review (Task 2) — выполнено отдельно на prod 0 inactive ADMIN (3/3 active, никого не удалял), 1 unused API key revoked (`ek_live_987f`), PM2 env audit-даты → 2026-06-20.
[CL-SEC] аудит Q2: 2FA-гейт на high-value отклонение выплат (rejectPayout)
Some checks failed
CI / API (pull_request) Has been cancelled
CI / App (pull_request) Has been cancelled
CI / Contracts (pull_request) Has been cancelled
CI / Telegram Mini App (pull_request) Has been cancelled
CI / Python SDK (pull_request) Has been cancelled
CI / Secrets Scan (pull_request) Has been cancelled
CI / Prisma Migrate Gate (pull_request) Has been cancelled
PR Janitor / janitor (pull_request) Has been cancelled
a0d2a5f1ad
rejectPayout кредитует EUR-баланс пользователя (income-payout/admin-operations.ts:144),
но не требовал 2FA ни при какой сумме — в отличие от approvePayout (порог
PAYOUT_2FA_THRESHOLD_EUR). Скомпрометированная admin-сессия без TOTP могла начислять
баланс через reject. Добавлен тот же пороговый 2FA-гейт + twoFactorCode в rejectPayoutSchema.

AUDIT: SEC-Q2-2026
AUDIT: SEC-Q2-2026
[CL-SEC] аудит Q2: отчёт — access review выполнен, remediation order обновлён
Some checks failed
CI / Contracts (pull_request) Successful in 1m55s
CI / Telegram Mini App (pull_request) Successful in 1m29s
CI / Python SDK (pull_request) Successful in 23s
CI / Secrets Scan (pull_request) Successful in 17s
CI / Prisma Migrate Gate (pull_request) Successful in 1m51s
PR Janitor / janitor (pull_request) Successful in 7s
CI / API (pull_request) Failing after 13m6s
CI / App (pull_request) Successful in 15m47s
a0ce32b94d
AUDIT: SEC-Q2-2026
andrei changed title from [CL-SEC] аудит Q2: admin-secret gate на force-expire/refund платёжных маршрутов to [CL-SEC] аудит Q2: admin-secret + 2FA гейты на money-маршрутах (force-expire/refund/reject) 2026-06-20 10:34:37 +00:00
[CL-SEC] аудит Q2: #3 fixed (PR #784), #4/#5 disproven при верификации
Some checks failed
CI / Contracts (pull_request) Has been cancelled
CI / Telegram Mini App (pull_request) Has been cancelled
CI / Python SDK (pull_request) Has been cancelled
CI / Secrets Scan (pull_request) Has been cancelled
CI / Prisma Migrate Gate (pull_request) Has been cancelled
CI / API (pull_request) Has been cancelled
PR Janitor / janitor (pull_request) Has been cancelled
CI / App (pull_request) Has been cancelled
React Doctor / React Doctor / App (pull_request) Successful in 2m49s
0b244af009
CRITICAL #4 (KYC TOCTOU) и #5 (NOWPayments idempotency-before-HMAC) не подтвердились
при root-cause investigation: #4 защищён атомарным unique-constraint create+P2002-exit
(loser не доходит до обработки); #5 уже митигирован — HMAC проверяется первым, при провале
res.locals.webhookSignatureInvalid → idempotency.ts:227-229 release-without-cache (W14-B1.1).
Фикс не применялся (phantom fix = нарушение systematic-debugging Iron Law).

AUDIT: SEC-Q2-2026
[CL-SEC] аудит Q2 (code-review): requireAdminSecretVerified на payout approve/reject
All checks were successful
CI / Contracts (pull_request) Successful in 1m56s
CI / Telegram Mini App (pull_request) Successful in 1m19s
CI / Python SDK (pull_request) Successful in 31s
CI / Secrets Scan (pull_request) Successful in 15s
PR Janitor / janitor (pull_request) Successful in 8s
CI / Prisma Migrate Gate (pull_request) Successful in 1m38s
CI / API (pull_request) Successful in 12m42s
CI / App (pull_request) Successful in 15m51s
7d3bdc8001
Code-review нашёл BLOCK: /payouts/:id/approve (SEPA/crypto transfer) и /reject (кредит
EUR-баланса) не имели route-level admin-secret gate, который есть у всех /payments/*
money-маршрутов. Контроллерный 2FA-код (≥€10K) этого не покрывал. Добавлен gate на оба;
structural-тест расширен на payout-маршруты; добавлены reject-тесты (malformed 2FA → error,
admin без 2FA → 403) для паритета с approve.

AUDIT: SEC-Q2-2026
andrei merged commit 9d247f07cb into master 2026-06-20 12:04:16 +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!781
No description provided.