Harden admin route visibility: 404 not 403, redirect to /login
- 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 <noreply@anthropic.com>
This commit is contained in:
+4
-2
@@ -36,8 +36,10 @@ async def get_current_admin(
|
|||||||
current_user: User = Depends(get_current_user),
|
current_user: User = Depends(get_current_user),
|
||||||
) -> User:
|
) -> User:
|
||||||
if not current_user.is_superuser:
|
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(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_403_FORBIDDEN,
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
detail="Admin access required",
|
detail="Not found",
|
||||||
)
|
)
|
||||||
return current_user
|
return current_user
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ function AdminRoute({ children }: { children: React.ReactNode }) {
|
|||||||
if (!token) return <Navigate to="/login" replace />;
|
if (!token) return <Navigate to="/login" replace />;
|
||||||
// Wait for the me query before deciding — prevents a flash redirect
|
// Wait for the me query before deciding — prevents a flash redirect
|
||||||
if (isLoading) return null;
|
if (isLoading) return null;
|
||||||
if (!user?.is_admin) return <Navigate to="/" replace />;
|
// Redirect to /login (not /) so the route appears not to exist
|
||||||
|
if (!user?.is_admin) return <Navigate to="/login" replace />;
|
||||||
return <>{children}</>;
|
return <>{children}</>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user