Commit Graph
2 Commits
Author SHA1 Message Date
splitsec2 b246c6617b fix(app_setup): create the secret key file private instead of tightening it after the write (#1659)
load_or_create_secret_key writes the Flask secret with write_bytes and
then chmods it to 0600. Until the chmod the key sits in a file with
whatever the umask allows, and if the chmod fails it stays that way and
only a warning is logged. The file is now opened with mode 0600, an
existing one is fchmod'ed before anything is written, and then the key
goes in. The new test makes chmod fail and checks the file still ends up
private, which fails on main.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

<!-- coderabbit-ai-generated:v1 -->

## Summary by CodeRabbit

* **Bug Fixes**
* Secret-key files now receive restrictive permissions when created or
replaced, helping prevent unauthorized access to the stored key.
* Key creation maintains these permissions even when a later
permission-setting operation fails.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-11-04 00:38:27 -06:00
splitsec2 f06585aa01 refactor: move the secret key, session cookie, security headers and log filter into core/app_setup.py (#1639)
`main.py` also builds the app itself, and this moves the parts of that
which need no route into `core/app_setup.py`: the persisted secret key
and the session cookie settings, the security headers, and the filter
that keeps status polling and the WebSocket upgrade noise out of the
log. It is the app setup item in the plan from Discussion #1536.

The first commit adds 14 tests for them, since none existed: the key
reused, created with mode 600, replaced when too short, and still
returned when the config directory cannot be written, the cookie
settings, the headers on a real response and that a header a route set
itself is kept, and each case the log filter drops or keeps. They pass
on current `main`. The second commit is the move.

The security headers hook is registered from the same spot in `main.py`
as before, so the `after_request` order is unchanged. The secret key
function takes the config directory as a parameter instead of reading
`CONFIG_DIR`, which is the one change in the move, and the key tests
call it with a temp directory.

The URL map and the hook order are identical, and the full suite, ruff
and basedpyright are clean. I also ran the app from the branch: the
secret file is created with mode 600 and the four security headers come
back on a normal response.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
<!-- coderabbit-ai-generated:v1 -->

## Summary by CodeRabbit

* **Bug Fixes**
* Sessions now remain consistent across app restarts, and session
cookies use more protective browser settings, including HTTP-only access
and a seven-day lifetime.
* Responses include baseline security headers while preserving any
headers already set by the app.
* Routine status-polling and connection-upgrade messages are filtered
from application logs, reducing unrelated log noise.
* If saving a session key fails, the app can still start with a
generated key.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-11-01 18:21:49 -07:00