blitz_api/app/setup
fusion44 97cbd4cb55
fix(setup): make input validation effective and tighten setup endpoints
password_valid()/name_valid() ended in `return re.match(...)`, which yields a
Match object or None. The setup router tests them with `is False`, and
`None is False` is False, so the charset check never rejected anything --
only the length and space rules were doing any work. The validators now return
real booleans, and use fullmatch: with re.match the trailing `$` also matches
just before a final newline.

Impact is bounded, and this is a correctness bug rather than a vulnerability.
These call sites are reachable only while the node is in `state=waitsetup`,
and that same endpoint hands the caller a signed admin JWT by design, on a
device where blitzapi has passwordless sudo. A malformed hostname reaching the
setup file -- which provisioning sources as bash -- therefore grants nothing
the caller does not already have, and in practice the value comes from the
operator's own setup form. What it does cost: a hostname containing a quote or
`$` corrupts the setup file and breaks provisioning, and the charset gate
would not hold as a defence if the setup flow ever gains operator binding.

Also in this change:

- Gate /setup-start-done and /setup-start-info on setupPhase != "done", as
  /setup/shutdown already does. `state` lives in the unauthenticated key-value
  store, so a local process could flip it back to "waitsetup" on a fully
  provisioned node and be handed an admin JWT. Unlike the above, that is a
  real escalation, because setup is supposed to be closed at that point.
- raise HTTPException instead of returning it (18 sites). FastAPI serialised
  the returned object as a 200 body, so rejections looked like successes; the
  WebUI stored that body as its access token.
- Fix the status.status.HTTP_405_METHOD_NOT_ALLOWED typo (3 sites) that raised
  AttributeError and surfaced as an unhandled 500.
- Create the setup file 0600. It holds passwords A/B/C in cleartext and
  provisioning appends the wallet seed words, on a tmpfs mounted mode=0777.

Regression tests in tests/test_setup_input_validation.py; all nine fail before
this change and pass after.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-16 10:51:07 +02:00
..
impl fix(setup): make input validation effective and tighten setup endpoints 2026-08-16 10:51:07 +02:00
__init__.py refactor: switch to domain driven directory layout 2022-10-03 20:22:00 +02:00
README.md refactor: switch to domain driven directory layout 2022-10-03 20:22:00 +02:00
router.py feat: make config loading more flexible 2025-03-23 17:43:39 +01:00

Setup

Since the setup is not highly specific to the underlying platform, we don't provide an abstraction to it like in the other parts of the framework. Instead, the platform implementation itself should provide a router that is simply attached to the main router in main.py by the API.