From 041fba4df4def4393584afb0ee68fb0d1b6fe44c Mon Sep 17 00:00:00 2001 From: VectorPeak Date: Sun, 5 Jul 2026 09:34:38 +0800 Subject: [PATCH] fix: enforce ownership when reading ChatUI sessions (#9141) --- astrbot/dashboard/services/chat_service.py | 6 ++- tests/test_dashboard.py | 45 ++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/astrbot/dashboard/services/chat_service.py b/astrbot/dashboard/services/chat_service.py index c471242e1..afbe4bd4c 100644 --- a/astrbot/dashboard/services/chat_service.py +++ b/astrbot/dashboard/services/chat_service.py @@ -1196,7 +1196,11 @@ class ChatService: async def get_session(self, username: str, session_id: str) -> dict: session = await self.db.get_platform_session_by_id(session_id) - platform_id = session.platform_id if session else "webchat" + if not session: + raise ChatServiceError(f"Session {session_id} not found") + if session.creator != username: + raise ChatServiceError("Permission denied") + platform_id = session.platform_id project_info = await self.db.get_project_by_session( session_id=session_id, creator=username diff --git a/tests/test_dashboard.py b/tests/test_dashboard.py index b28c2643a..16356fbab 100644 --- a/tests/test_dashboard.py +++ b/tests/test_dashboard.py @@ -2217,6 +2217,51 @@ async def test_batch_delete_sessions_uses_batch_lookup( assert called["batch_lookup_count"] == 1 +@pytest.mark.asyncio +@pytest.mark.parametrize( + "path_template", + [ + "/api/chat/get_session?session_id={session_id}", + "/api/v1/chat/sessions/{session_id}", + ], +) +async def test_get_chat_session_rejects_session_owned_by_another_user( + app: FastAPIAppAdapter, + authenticated_header: dict, + core_lifecycle_td: AstrBotCoreLifecycle, + path_template: str, +): + test_client = app.test_client() + session_id = f"foreign_get_session_{uuid.uuid4().hex[:8]}" + await core_lifecycle_td.db.create_platform_session( + creator="not_dashboard_user", + platform_id="webchat", + session_id=session_id, + display_name="Foreign Session", + is_group=0, + ) + await core_lifecycle_td.platform_message_history_manager.insert( + platform_id="webchat", + user_id=session_id, + content={ + "type": "user", + "message": [{"type": "text", "text": "foreign session secret"}], + }, + sender_id="not_dashboard_user", + sender_name="not_dashboard_user", + ) + + response = await test_client.get( + path_template.format(session_id=session_id), + headers=authenticated_header, + ) + + assert response.status_code == 200 + data = await response.get_json() + assert data["status"] == "error" + assert data["message"] == "Permission denied" + + @pytest.mark.asyncio async def test_plugins( app: FastAPIAppAdapter,