diff --git a/autogpt_platform/backend/backend/api/features/chat/sdk/security_hooks.py b/autogpt_platform/backend/backend/api/features/chat/sdk/security_hooks.py index 283806d676..f2e6d8f899 100644 --- a/autogpt_platform/backend/backend/api/features/chat/sdk/security_hooks.py +++ b/autogpt_platform/backend/backend/api/features/chat/sdk/security_hooks.py @@ -138,12 +138,15 @@ def create_security_hooks(user_id: str | None) -> dict[str, Any]: tool_input = cast(dict[str, Any], input_data.get("tool_input", {})) # Strip MCP prefix for consistent validation + is_copilot_tool = tool_name.startswith(MCP_TOOL_PREFIX) clean_name = tool_name.removeprefix(MCP_TOOL_PREFIX) - # Validate basic tool access - result = _validate_tool_access(clean_name, tool_input) - if result: - return cast(SyncHookJSONOutput, result) + # Only block non-CoPilot tools; our MCP-registered tools + # (including Read for oversized results) are already sandboxed. + if not is_copilot_tool: + result = _validate_tool_access(clean_name, tool_input) + if result: + return cast(SyncHookJSONOutput, result) # Validate user isolation result = _validate_user_isolation(clean_name, tool_input, user_id) @@ -259,10 +262,13 @@ def create_strict_security_hooks( }, ) - # Run standard validations using clean_name for consistent checks - result = _validate_tool_access(clean_name, tool_input) - if result: - return cast(SyncHookJSONOutput, result) + # Only run blocklist check for non-CoPilot tools; whitelisted + # MCP tools are already sandboxed by tool_adapter. + is_copilot_tool = tool_name.startswith(MCP_TOOL_PREFIX) + if not is_copilot_tool: + result = _validate_tool_access(clean_name, tool_input) + if result: + return cast(SyncHookJSONOutput, result) result = _validate_user_isolation(clean_name, tool_input, user_id) if result: diff --git a/autogpt_platform/backend/backend/api/features/chat/service.py b/autogpt_platform/backend/backend/api/features/chat/service.py index e6144a75b4..bcce938508 100644 --- a/autogpt_platform/backend/backend/api/features/chat/service.py +++ b/autogpt_platform/backend/backend/api/features/chat/service.py @@ -452,8 +452,9 @@ async def stream_chat_completion( # Generate title for new sessions on first user message (non-blocking) # Check: is_user_message, no title yet, and this is the first user message - if is_user_message and message and not session.title: - user_messages = [m for m in session.messages if m.role == "user"] + user_messages = [m for m in session.messages if m.role == "user"] + first_user_msg = message or (user_messages[0].content if user_messages else None) + if is_user_message and first_user_msg and not session.title: if len(user_messages) == 1: # First user message - generate title in background import asyncio @@ -461,7 +462,7 @@ async def stream_chat_completion( # Capture only the values we need (not the session object) to avoid # stale data issues when the main flow modifies the session captured_session_id = session_id - captured_message = message + captured_message = first_user_msg captured_user_id = user_id async def _update_title():