Fix camera name collision bypassing admin check (#24516)

* don't let camera names waive the admin check on non-camera routes

The global admin guard skipped the admin check for any request whose first path segment matched a configured camera name, without looking at which route actually handled it. A camera named `faces`, `lpr`, `audio`, or `classification` let viewers reach the face, LPR, audio transcription, and classification endpoints that rely only on the global guard. The exemption now also requires the matched route to be a `/{camera_name}` route, so camera routes behave exactly as before.

* add test
This commit is contained in:
Josh Hawkins
2026-10-01 08:56:04 -06:00
committed by GitHub
parent 160d213025
commit 17a8efa09c
3 changed files with 35 additions and 19 deletions
+12 -17
View File
@@ -127,23 +127,18 @@ def require_admin_by_default():
if path.startswith(EXEMPT_PREFIXES):
return
# Dynamic camera path exemption:
# Any path whose first segment matches a configured camera name should
# bypass the global admin requirement. These endpoints enforce access
# via route-level dependencies (e.g. require_camera_access) to ensure
# per-camera authorization. This allows non-admin authenticated users
# (e.g. viewer role) to access camera-specific resources without
# needing admin privileges.
try:
if path.startswith("/"):
first_segment = path.split("/", 2)[1]
if (
first_segment
and first_segment in request.app.frigate_config.cameras
):
return
except Exception:
pass
# Camera routes enforce per-camera access via route-level dependencies
# (e.g. require_camera_access). Match on the route template, not the raw
# path, so a camera named like another namespace (e.g. "faces") can't
# waive the admin check for that namespace's routes.
route = request.scope.get("route")
if (
route is not None
and route.path.startswith("/{camera_name}")
and request.path_params.get("camera_name")
in request.app.frigate_config.cameras
):
return
# For all other paths, require admin role
# Internal port requests have admin role set automatically