From 87c7cc193a4dd7f9d26d1334c23890bf355e81ca Mon Sep 17 00:00:00 2001 From: curo1305 Date: Mon, 13 Apr 2026 18:46:33 +0200 Subject: [PATCH] Harden admin route visibility: 404 not 403, redirect to /login MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - deps.py: get_current_admin returns 404 Not Found for non-superusers instead of 403 Forbidden — hides endpoint existence from unauthorised callers - App.tsx: AdminRoute redirects non-admins to /login instead of /, making the route indistinguishable from a non-existent page Layer 3 (network-level IP restriction via Traefik) tracked in TODO. Co-Authored-By: Claude Sonnet 4.6 --- backend/app/deps.py | 6 ++++-- frontend/src/App.tsx | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/backend/app/deps.py b/backend/app/deps.py index df0cc68..454cab7 100644 --- a/backend/app/deps.py +++ b/backend/app/deps.py @@ -36,8 +36,10 @@ async def get_current_admin( current_user: User = Depends(get_current_user), ) -> User: if not current_user.is_superuser: + # Return 404 instead of 403 — reveals neither the existence of the + # endpoint nor that the caller lacks permission. raise HTTPException( - status_code=status.HTTP_403_FORBIDDEN, - detail="Admin access required", + status_code=status.HTTP_404_NOT_FOUND, + detail="Not found", ) return current_user diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 44ba8ec..18c534a 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -21,7 +21,8 @@ function AdminRoute({ children }: { children: React.ReactNode }) { if (!token) return ; // Wait for the me query before deciding — prevents a flash redirect if (isLoading) return null; - if (!user?.is_admin) return ; + // Redirect to /login (not /) so the route appears not to exist + if (!user?.is_admin) return ; return <>{children}; }