[SECURITY][P1] tradein/team: имя из roles.yaml при создании сотрудника даёт эскалацию до admin — IDOR по всем оценкам и безлимит квоты #3316

Closed
opened 2026-09-02 06:51:27 +00:00 by bot-backend · 0 comments
Collaborator

Из максимального аудита 01-02.09 (линза payments-auth), подтверждено скептиком по коду и проду. Двусторонний дефект одного корня: роль живёт в YAML-реестре, пользователи — в БД, и никто не сверяет одно с другим.

Сторона 1 — эскалация вверх

team.py:436-441: create_employee проверяет username только regex-ом и уникальностью в БД. Резерв-листа по roles.yaml нет. Менеджер создаёт сотрудника с именем, которое уже числится в roles.yaml с ролью admin (например admintest) — и этот «сотрудник» при входе получает роль ИЗ РЕЕСТРА:

  • trade_in.py:159-168: ownership-check пропускает admin → читает любые оценки всех клиентов (IDOR);
  • account_quota.py: admin безлимитен → квота команды не действует.

Прод сейчас чист (13 юзеров, коллизий нет) — дыра не эксплуатировалась, но открыта.

Сторона 2 — та же причина, обратный знак

trade_in.py:162-168 (второй сайт :1177-1180): сотрудник, созданный через team-API и отсутствующий в roles.yaml, получает KeyError → 403 на чтение собственной оценки. Онбординг штатно производит нерабочие аккаунты: rbac_guard пускает по DB-роли, а get_role читает только YAML.

Лечение (обе стороны одним механизмом)

Единый источник ролей. Либо роль сотрудника ищется сначала в БД (tradein_users.role), а YAML остаётся только для legacy-админов с явным приоритетом БД; либо create_employee резервирует все имена из roles.yaml. Первое правильнее: убирает и 403-сторону.

Приёмка

  • Тест: создание сотрудника с именем из roles.yaml → либо отказ, либо роль employee (не admin из YAML)
  • Тест: сотрудник вне roles.yaml читает СВОЮ оценку (200), чужую — 403
  • Фальсификация: снятие фикса красит оба теста ПО ЗНАЧЕНИЮ
  • Прод-проверка после деплоя: роли всех 13 существующих юзеров не изменились

Refs: #2549 (эпик auth), #2558 (cutover — этот дефект переживёт cutover, чинится отдельно).

Из максимального аудита 01-02.09 (линза payments-auth), подтверждено скептиком по коду и проду. **Двусторонний дефект одного корня: роль живёт в YAML-реестре, пользователи — в БД, и никто не сверяет одно с другим.** ## Сторона 1 — эскалация вверх `team.py:436-441`: `create_employee` проверяет username только regex-ом и уникальностью в БД. **Резерв-листа по `roles.yaml` нет.** Менеджер создаёт сотрудника с именем, которое уже числится в `roles.yaml` с ролью admin (например `admintest`) — и этот «сотрудник» при входе получает роль ИЗ РЕЕСТРА: - `trade_in.py:159-168`: ownership-check пропускает admin → **читает любые оценки всех клиентов** (IDOR); - `account_quota.py`: admin безлимитен → квота команды не действует. Прод сейчас чист (13 юзеров, коллизий нет) — дыра не эксплуатировалась, но открыта. ## Сторона 2 — та же причина, обратный знак `trade_in.py:162-168` (второй сайт `:1177-1180`): сотрудник, созданный через team-API и **отсутствующий** в `roles.yaml`, получает `KeyError → 403` на чтение **собственной** оценки. Онбординг штатно производит нерабочие аккаунты: rbac_guard пускает по DB-роли, а get_role читает только YAML. ## Лечение (обе стороны одним механизмом) Единый источник ролей. Либо роль сотрудника ищется сначала в БД (tradein_users.role), а YAML остаётся только для legacy-админов с явным приоритетом БД; либо `create_employee` резервирует все имена из roles.yaml. Первое правильнее: убирает и 403-сторону. ## Приёмка - [ ] Тест: создание сотрудника с именем из roles.yaml → либо отказ, либо роль employee (не admin из YAML) - [ ] Тест: сотрудник вне roles.yaml читает СВОЮ оценку (200), чужую — 403 - [ ] Фальсификация: снятие фикса красит оба теста ПО ЗНАЧЕНИЮ - [ ] Прод-проверка после деплоя: роли всех 13 существующих юзеров не изменились Refs: #2549 (эпик auth), #2558 (cutover — этот дефект переживёт cutover, чинится отдельно).
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#3316
No description provided.