fix(chat/sdk): address PR #12103 review comments

- 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
This commit is contained in:
Zamil Majdy
2026-02-13 16:38:03 +04:00
parent 52c8a25531
commit 80e413b969
2 changed files with 7 additions and 13 deletions

View File

@@ -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:

View File

@@ -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)