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

Merged
NotBigGhost merged 1 commits from issue-69-public-dev into dev 2026-09-19 00:10:20 +03:00
Collaborator

Что сделано

Опубликованный dev (LOCAL_PUBLIC=vps) теперь проверяет секреты так же, как прод. Новое свойство Settings.is_published истинно для production и для dev на домене. Fail-fast по дефолтным или слабым SECRET_KEY/ADMIN_PASSWORD срабатывает при нём, а не только в production. На том же свойстве cookie_secure, его поведение не изменилось.

Stub-вход, dev-роутеры и Swagger на опубликованном dev по решению владельца остаются. Предупреждение о том, что открыто любому посетителю, выводят лог старта, run.ps1 и run.sh. В .env.example описано, что открывает vps, и что у dev и prod должны быть разные SECRET_KEY.

Модель угрозы

  • Атакующий — любой посетитель https://forbidden-stars.ru, пока у владельца запущен dev с LOCAL_PUBLIC=vps.

  • Закрыто:

    • вход в админку по общеизвестному паролю change-me-admin-password;
    • подделка JWT общеизвестным ключом change-me-dev-secret-not-for-production — в том числе админского fs_admin, а через него и жёсткое удаление аккаунтов DELETE /api/admin/dev/users/{id}.
  • Остаётся сознательно (решение владельца):

    • вход под любым игроком dev-базы через stub;
    • GET/POST /api/auth/dev/users;
    • Swagger.

    Смягчение — предупреждения при старте. Вывод: в dev-базе не должно быть копии прод-данных.

  • Общий ключ dev и prod. Если он совпадает, токен, подписанный на dev, прошёл бы на проде. Код этого не проверяет: контуры на разных машинах. Правило записано в .env.example.

Что проверено

  • pytest — 215 passed. В test_config_security.py 6 новых проверок:

    • dev+vps отказывает при дефолтном ключе, коротком ключе и дефолтном пароле админа;
    • dev+vps с сильными секретами стартует;
    • при старте опубликованного dev в логе есть предупреждение, у localhost-dev его нет;
    • dev+local с дефолтами стартует, cookie_secure=false.

    На старом коде (config.py/main.py из dev) эти проверки падают: 6 failed.

  • Вручную: APP_ENV=development LOCAL_PUBLIC=vps с дефолтами из .env.example → импорт app.core.config падает с «Небезопасная конфигурация dev, опубликованного наружу (LOCAL_PUBLIC=vps)…».

  • run.ps1 — 0 не-ASCII байт.

Коммиты

  • cff48f7 Безопасность: опубликованный dev не стартует с дефолтными секретами

Отклонения от плана

Нет.

Что сделать владельцу: если в dev-.env на ПК остались дефолтные SECRET_KEY/ADMIN_PASSWORD, то с LOCAL_PUBLIC=vps бэкенд не поднимется, пока их не заменить. Ключ генерируется командой python -c "import secrets;print(secrets.token_urlsafe(48))", он должен отличаться от прод-ключа.

Closes #69

🤖 Generated with Claude Code

https://claude.ai/code/session_01LqSoRj99iwVEH5U5fnZgsd

## Что сделано Опубликованный dev (`LOCAL_PUBLIC=vps`) теперь проверяет секреты так же, как прод. Новое свойство `Settings.is_published` истинно для production и для dev на домене. Fail-fast по дефолтным или слабым `SECRET_KEY`/`ADMIN_PASSWORD` срабатывает при нём, а не только в production. На том же свойстве `cookie_secure`, его поведение не изменилось. Stub-вход, dev-роутеры и Swagger на опубликованном dev по решению владельца **остаются**. Предупреждение о том, что открыто любому посетителю, выводят лог старта, `run.ps1` и `run.sh`. В `.env.example` описано, что открывает `vps`, и что у dev и prod должны быть разные `SECRET_KEY`. ## Модель угрозы - **Атакующий** — любой посетитель https://forbidden-stars.ru, пока у владельца запущен dev с `LOCAL_PUBLIC=vps`. - **Закрыто:** - вход в админку по общеизвестному паролю `change-me-admin-password`; - подделка JWT общеизвестным ключом `change-me-dev-secret-not-for-production` — в том числе админского `fs_admin`, а через него и жёсткое удаление аккаунтов `DELETE /api/admin/dev/users/{id}`. - **Остаётся сознательно** (решение владельца): - вход под любым игроком dev-базы через stub; - `GET/POST /api/auth/dev/users`; - Swagger. Смягчение — предупреждения при старте. Вывод: в dev-базе не должно быть копии прод-данных. - **Общий ключ dev и prod.** Если он совпадает, токен, подписанный на dev, прошёл бы на проде. Код этого не проверяет: контуры на разных машинах. Правило записано в `.env.example`. ## Что проверено - `pytest` — 215 passed. В `test_config_security.py` 6 новых проверок: - dev+vps отказывает при дефолтном ключе, коротком ключе и дефолтном пароле админа; - dev+vps с сильными секретами стартует; - при старте опубликованного dev в логе есть предупреждение, у localhost-dev его нет; - dev+local с дефолтами стартует, `cookie_secure=false`. На старом коде (`config.py`/`main.py` из `dev`) эти проверки падают: 6 failed. - Вручную: `APP_ENV=development LOCAL_PUBLIC=vps` с дефолтами из `.env.example` → импорт `app.core.config` падает с «Небезопасная конфигурация dev, опубликованного наружу (LOCAL_PUBLIC=vps)…». - `run.ps1` — 0 не-ASCII байт. ## Коммиты - `cff48f7` Безопасность: опубликованный dev не стартует с дефолтными секретами ## Отклонения от плана Нет. **Что сделать владельцу:** если в dev-`.env` на ПК остались дефолтные `SECRET_KEY`/`ADMIN_PASSWORD`, то с `LOCAL_PUBLIC=vps` бэкенд не поднимется, пока их не заменить. Ключ генерируется командой `python -c "import secrets;print(secrets.token_urlsafe(48))"`, он должен отличаться от прод-ключа. Closes #69 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01LqSoRj99iwVEH5U5fnZgsd
Agent added 1 commit 2026-09-18 23:52:42 +03:00
При LOCAL_PUBLIC=vps dev доступен на forbidden-stars.ru, а fail-fast по
SECRET_KEY/ADMIN_PASSWORD работал только в production: снаружи оставались
общеизвестный ключ JWT (подделка любого токена, включая админский) и пароль
админки. Теперь проверка срабатывает при is_published — у прода и у dev на
домене; на нём же cookie_secure.

Dev-инструменты и Swagger на опубликованном dev остаются (решение владельца):
лаунчеры и лог старта перечисляют, что открыто любому посетителю. В .env.example —
что открывает vps и что у dev и prod должны быть разные SECRET_KEY. #69

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LqSoRj99iwVEH5U5fnZgsd
NotBigGhost merged commit 03834c6855 into dev 2026-09-19 00:10:20 +03:00
NotBigGhost deleted branch issue-69-public-dev 2026-09-19 00:10:20 +03:00
Sign in to join this conversation.