Finding
Every handler registered by zone_routes() — create_zone, delete_zone, list_zones, get_zone, add_member, remove_member, zone_play, zone_pause, zone_resume — takes only State(state) plus path/body extractors. None carries an AuthenticatedUser or RequireAdmin extractor, so all nine zone-management endpoints are reachable by any unauthenticated client that can reach the LAN listener.
Evidence
crates/paroche/src/routes/zone.rs:61 — the create_zone entry point:
pub async fn create_zone(
State(state): State<AppState>,
Json(body): Json<CreateZoneBody>,
No auth extractor is present here or in the sibling handlers. crates/paroche/src/routes/zone.rs:179 (zone_crud_lifecycle) drives the full create/member/playback lifecycle without creating a user or sending an Authorization header, so the absence of auth is asserted as intended behavior rather than an oversight in one handler.
Why this matters
The threat model treats any LAN-resident or authenticated-but-low-privilege device as hostile. An unauthenticated device on the same network can enumerate zones, attach or detach renderers, and trigger play/pause/resume across every connected client. Against a capable adversary this is both a control surface (forced playback/membership changes disrupt or surveil active renderers) and a reconnaissance surface (zone topology reveals which devices and rooms are active).
Desired correction
Add an auth extractor to every handler in zone_routes(). Playback controls (zone_play, zone_pause, zone_resume) require at least AuthenticatedUser; zone creation/deletion and member add/remove require RequireAdmin. Mirror the extractor pattern already used in renderer.rs and user.rs.
Done when: unauthenticated requests to any /api/zones/* route return 401, confirmed by tests parallel to those already present in renderer.rs and user.rs.
Finding
Every handler registered by
zone_routes()—create_zone,delete_zone,list_zones,get_zone,add_member,remove_member,zone_play,zone_pause,zone_resume— takes onlyState(state)plus path/body extractors. None carries anAuthenticatedUserorRequireAdminextractor, so all nine zone-management endpoints are reachable by any unauthenticated client that can reach the LAN listener.Evidence
crates/paroche/src/routes/zone.rs:61— thecreate_zoneentry point:No auth extractor is present here or in the sibling handlers.
crates/paroche/src/routes/zone.rs:179(zone_crud_lifecycle) drives the full create/member/playback lifecycle without creating a user or sending anAuthorizationheader, so the absence of auth is asserted as intended behavior rather than an oversight in one handler.Why this matters
The threat model treats any LAN-resident or authenticated-but-low-privilege device as hostile. An unauthenticated device on the same network can enumerate zones, attach or detach renderers, and trigger play/pause/resume across every connected client. Against a capable adversary this is both a control surface (forced playback/membership changes disrupt or surveil active renderers) and a reconnaissance surface (zone topology reveals which devices and rooms are active).
Desired correction
Add an auth extractor to every handler in
zone_routes(). Playback controls (zone_play,zone_pause,zone_resume) require at leastAuthenticatedUser; zone creation/deletion and member add/remove requireRequireAdmin. Mirror the extractor pattern already used inrenderer.rsanduser.rs.Done when: unauthenticated requests to any
/api/zones/*route return 401, confirmed by tests parallel to those already present inrenderer.rsanduser.rs.