From 80e413b9690584e5157e7bf9c7751ada530090d4 Mon Sep 17 00:00:00 2001 From: Zamil Majdy Date: Fri, 13 Feb 2026 16:38:03 +0400 Subject: [PATCH] fix(chat/sdk): address PR #12103 review comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove duplicate security check in _cleanup_sdk_tool_results (copy-paste) - Don't delete transcript on transient errors — only the current turn failed, the transcript is still valid for future resume - Add post-construction realpath check in write_transcript_to_tempfile to satisfy CodeQL taint analysis --- .../backend/api/features/chat/sdk/service.py | 13 +------------ .../backend/api/features/chat/sdk/transcript.py | 7 ++++++- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/autogpt_platform/backend/backend/api/features/chat/sdk/service.py b/autogpt_platform/backend/backend/api/features/chat/sdk/service.py index a89807d0e4..65195b442c 100644 --- a/autogpt_platform/backend/backend/api/features/chat/sdk/service.py +++ b/autogpt_platform/backend/backend/api/features/chat/sdk/service.py @@ -46,7 +46,6 @@ from .tool_adapter import ( set_execution_context, ) from .transcript import ( - delete_transcript, download_transcript, read_transcript_file, upload_transcript, @@ -278,13 +277,8 @@ def _cleanup_sdk_tool_results(cwd: str) -> None: """ import shutil - # Security check 1: Validate cwd is under the expected prefix + # Validate cwd is under the expected prefix normalized = os.path.normpath(cwd) - if not normalized.startswith(_SDK_CWD_PREFIX): - logger.warning(f"[SDK] Rejecting cleanup for invalid path: {cwd}") - return - - # Security check 2: Verify path stayed within workspace after normalization if not normalized.startswith(_SDK_CWD_PREFIX): logger.warning(f"[SDK] Rejecting cleanup for path outside workspace: {cwd}") return @@ -718,11 +712,6 @@ async def stream_chat_completion_sdk( except Exception as e: logger.error(f"[SDK] Error: {e}", exc_info=True) - if use_resume and user_id: - logger.warning("[SDK] Deleting transcript after resume failure") - task = asyncio.create_task(delete_transcript(user_id, session_id)) - _background_tasks.add(task) - task.add_done_callback(_background_tasks.discard) try: await upsert_chat_session(session) except Exception as save_err: diff --git a/autogpt_platform/backend/backend/api/features/chat/sdk/transcript.py b/autogpt_platform/backend/backend/api/features/chat/sdk/transcript.py index d7295585d6..8c92168a40 100644 --- a/autogpt_platform/backend/backend/api/features/chat/sdk/transcript.py +++ b/autogpt_platform/backend/backend/api/features/chat/sdk/transcript.py @@ -180,7 +180,12 @@ def write_transcript_to_tempfile( try: os.makedirs(real_cwd, exist_ok=True) safe_id = _sanitize_id(session_id, max_len=8) - jsonl_path = os.path.join(real_cwd, f"transcript-{safe_id}.jsonl") + jsonl_path = os.path.realpath( + os.path.join(real_cwd, f"transcript-{safe_id}.jsonl") + ) + if not jsonl_path.startswith(real_cwd): + logger.warning(f"[Transcript] Path escaped cwd: {jsonl_path}") + return None with open(jsonl_path, "w") as f: f.write(transcript_content)