Dev, выставленный на forbidden-stars.ru (LOCAL_PUBLIC=vps), публичен с stub-входом и без проверки секретов #69

Closed
opened 2026-09-14 18:55:39 +03:00 by Agent · 2 comments
Collaborator

Обновлено: test-контур (docker-compose.test.yml, APP_ENV=test, restore-test) удалён из проекта. Теперь APP_ENV принимает только development/production (валидатор _known_app_env в config.py), поэтому часть задачи про публичный тест-клон с копией прод-данных больше не актуальна. Осталась ситуация с dev.

Проблема

Валидатор Settings._forbid_default_secrets_in_prod (backend/app/core/config.py) останавливает запуск с дефолтными SECRET_KEY / ADMIN_PASSWORD только при APP_ENV=production. Для dev это нормально, пока dev живёт на localhost.

Но лаунчер (run.ps1 / run.sh) при LOCAL_PUBLIC=vps выставляет dev на публичный домен https://forbidden-stars.ru через SSH-туннель. В таком режиме наружу открыты:

  • stub-вход по нику без пароля (POST /api/auth/dev/login). Любой посетитель войдёт под любым пользователем dev-базы; dev_login ищет пользователя по нику без проверки роли;
  • GET/POST /api/auth/dev/users — список и создание пользователей без аутентификации;
  • OpenAPI/Swagger (/api/docs) — полная карта API;
  • с дефолтным SECRET_KEY (change-me-dev-secret-not-for-production виден в репозитории) можно подделать JWT, в том числе админский fs_admin, и дальше вызывать dev-роутер жёсткого удаления аккаунтов DELETE /api/admin/dev/users/{id}.

Данные в dev-базе не прод, но это всё равно публичная точка с обходом аутентификации. Если в dev когда-либо окажется копия прод-данных, они будут открыты.

Что предлагается

  • При APP_ENV=development + LOCAL_PUBLIC=vps:
    • предупреждать в лаунчере и в логе старта, что наружу открыт stub-вход и Swagger; или
    • отключать stub-вход и dev-роутеры, пока dev опубликован (например, enabled_methods() и подключение dev_* в main.py смотрят ещё и на local_public), оставив их для localhost; и/или
    • применять fail-fast по дефолтным SECRET_KEY/ADMIN_PASSWORD и в этом режиме.
  • Задокументировать, что у dev и prod должны быть разные SECRET_KEY.

Найдено при сверке CLAUDE.md с кодом.

> **Обновлено:** test-контур (`docker-compose.test.yml`, `APP_ENV=test`, `restore-test`) удалён из проекта. Теперь `APP_ENV` принимает только `development`/`production` (валидатор `_known_app_env` в `config.py`), поэтому часть задачи про публичный тест-клон с копией прод-данных больше не актуальна. Осталась ситуация с dev. ## Проблема Валидатор `Settings._forbid_default_secrets_in_prod` (`backend/app/core/config.py`) останавливает запуск с дефолтными `SECRET_KEY` / `ADMIN_PASSWORD` **только при `APP_ENV=production`**. Для dev это нормально, пока dev живёт на localhost. Но лаунчер (`run.ps1` / `run.sh`) при `LOCAL_PUBLIC=vps` выставляет dev на **публичный** домен https://forbidden-stars.ru через SSH-туннель. В таком режиме наружу открыты: - **stub-вход по нику без пароля** (`POST /api/auth/dev/login`). Любой посетитель войдёт под любым пользователем dev-базы; `dev_login` ищет пользователя по нику без проверки роли; - `GET/POST /api/auth/dev/users` — список и создание пользователей без аутентификации; - OpenAPI/Swagger (`/api/docs`) — полная карта API; - с дефолтным `SECRET_KEY` (`change-me-dev-secret-not-for-production` виден в репозитории) можно подделать JWT, в том числе админский `fs_admin`, и дальше вызывать dev-роутер жёсткого удаления аккаунтов `DELETE /api/admin/dev/users/{id}`. Данные в dev-базе не прод, но это всё равно публичная точка с обходом аутентификации. Если в dev когда-либо окажется копия прод-данных, они будут открыты. ## Что предлагается - При `APP_ENV=development` + `LOCAL_PUBLIC=vps`: - предупреждать в лаунчере и в логе старта, что наружу открыт stub-вход и Swagger; **или** - отключать stub-вход и dev-роутеры, пока dev опубликован (например, `enabled_methods()` и подключение `dev_*` в `main.py` смотрят ещё и на `local_public`), оставив их для localhost; **и/или** - применять fail-fast по дефолтным `SECRET_KEY`/`ADMIN_PASSWORD` и в этом режиме. - Задокументировать, что у dev и prod должны быть **разные** `SECRET_KEY`. Найдено при сверке CLAUDE.md с кодом.
Agent added the
Priority
Medium
3
Kind/Security
labels 2026-09-14 18:55:39 +03:00
Agent changed title from Проверка дефолтных секретов работает только в production, а публичный test-контур с копией прод-данных не защищён to Dev, выставленный на forbidden-stars.ru (LOCAL_PUBLIC=vps), публичен с stub-входом и без проверки секретов 2026-09-14 20:20:54 +03:00
Agent self-assigned this 2026-09-18 23:46:11 +03:00
Agent added the
Reviewed
Confirmed
1
label 2026-09-18 23:46:13 +03:00
Author
Collaborator

План выполнения

Решения владельца: stub-вход, dev-роутеры и Swagger на публичном dev остаются, но об их открытости нужно явно предупреждать.

  1. config.py: свойство is_published (production либо dev с LOCAL_PUBLIC ≠ local) — на нём же cookie_secure. Fail-fast по дефолтным или слабым SECRET_KEY/ADMIN_PASSWORD срабатывает при is_published, а не только в production.
  2. Предупреждение в лог при старте опубликованного dev: вход по нику без пароля, список и создание игроков, жёсткое удаление аккаунтов, Swagger; совет не держать в dev-БД прод-данные.
  3. То же предупреждение в run.ps1 (ASCII) и run.sh рядом с Public: https://forbidden-stars.ru.
  4. .env.example: что открывает vps; у dev и prod разные SECRET_KEY.
  5. Тесты в test_config_security.py для dev+vps и dev+local.

Модель угрозы. Закрывается вход в админку по общеизвестному паролю и подделка JWT общеизвестным ключом (в том числе админского — и через него жёсткое удаление аккаунтов). Сознательно остаётся вход под любым игроком dev-базы через stub.

Критерии готовности

  • Опубликованный dev с дефолтными или слабыми секретами не стартует и объясняет почему; localhost-dev стартует с дефолтами, как раньше.
  • Лаунчер и лог старта перечисляют, что открыто наружу.
  • pytest зелёный, новые тесты на старом коде падают; run.ps1 без не-ASCII.

Ветка: issue-69-public-dev от dev

## План выполнения Решения владельца: stub-вход, dev-роутеры и Swagger на публичном dev **остаются**, но об их открытости нужно явно предупреждать. 1. `config.py`: свойство `is_published` (production либо dev с `LOCAL_PUBLIC` ≠ `local`) — на нём же `cookie_secure`. Fail-fast по дефолтным или слабым `SECRET_KEY`/`ADMIN_PASSWORD` срабатывает при `is_published`, а не только в production. 2. Предупреждение в лог при старте опубликованного dev: вход по нику без пароля, список и создание игроков, жёсткое удаление аккаунтов, Swagger; совет не держать в dev-БД прод-данные. 3. То же предупреждение в `run.ps1` (ASCII) и `run.sh` рядом с `Public: https://forbidden-stars.ru`. 4. `.env.example`: что открывает `vps`; у dev и prod разные `SECRET_KEY`. 5. Тесты в `test_config_security.py` для dev+vps и dev+local. **Модель угрозы.** Закрывается вход в админку по общеизвестному паролю и подделка JWT общеизвестным ключом (в том числе админского — и через него жёсткое удаление аккаунтов). Сознательно остаётся вход под любым игроком dev-базы через stub. **Критерии готовности** - Опубликованный dev с дефолтными или слабыми секретами не стартует и объясняет почему; localhost-dev стартует с дефолтами, как раньше. - Лаунчер и лог старта перечисляют, что открыто наружу. - `pytest` зелёный, новые тесты на старом коде падают; `run.ps1` без не-ASCII. **Ветка:** `issue-69-public-dev` от `dev`
Agent added the
Status
In Review
label 2026-09-18 23:52:45 +03:00
Author
Collaborator

Работа выполнена, открыт PR: #92

Итог: dev на домене (LOCAL_PUBLIC=vps) больше не стартует с дефолтными или слабыми SECRET_KEY/ADMIN_PASSWORD — закрыты вход в админку по известному паролю и подделка JWT. Stub-вход, dev-роутеры и Swagger остаются (решение владельца), а лог старта и лаунчеры предупреждают, что они открыты наружу.
Проверки: pytest — 215 passed (6 новых проверок падают на старом коде); ручной старт с дефолтами при vps — понятный отказ; run.ps1 — ASCII.
Статус: Status/In Review
Осталось за вами: ревью и мёрж PR — задача закроется автоматически. Если в dev-.env дефолтные секреты — заменить до следующего запуска с vps.

Работа выполнена, открыт PR: https://gitea.arseniev.info/NotBigGhost/ForbiddenStarsApp/pulls/92 **Итог:** dev на домене (`LOCAL_PUBLIC=vps`) больше не стартует с дефолтными или слабыми `SECRET_KEY`/`ADMIN_PASSWORD` — закрыты вход в админку по известному паролю и подделка JWT. Stub-вход, dev-роутеры и Swagger остаются (решение владельца), а лог старта и лаунчеры предупреждают, что они открыты наружу. **Проверки:** `pytest` — 215 passed (6 новых проверок падают на старом коде); ручной старт с дефолтами при `vps` — понятный отказ; `run.ps1` — ASCII. **Статус:** `Status/In Review` **Осталось за вами:** ревью и мёрж PR — задача закроется автоматически. Если в dev-`.env` дефолтные секреты — заменить до следующего запуска с `vps`.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: NotBigGhost/ForbiddenStarsApp#69