Опубликованный 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))", он должен отличаться от прод-ключа.
## Что сделано
Опубликованный 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
При 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
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Что сделано
Опубликованный 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;change-me-dev-secret-not-for-production— в том числе админскогоfs_admin, а через него и жёсткое удаление аккаунтовDELETE /api/admin/dev/users/{id}.Остаётся сознательно (решение владельца):
GET/POST /api/auth/dev/users;Смягчение — предупреждения при старте. Вывод: в dev-базе не должно быть копии прод-данных.
Общий ключ dev и prod. Если он совпадает, токен, подписанный на dev, прошёл бы на проде. Код этого не проверяет: контуры на разных машинах. Правило записано в
.env.example.Что проверено
pytest— 215 passed. Вtest_config_security.py6 новых проверок: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