From 9fa4c017f036b91761eafe69305749527dac958b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=B0=91=E6=9D=B0?= Date: Tue, 7 Apr 2026 17:39:21 +0800 Subject: [PATCH] fix(dashboard): use secure temp file for batch analysis scripts Batch portfolio analysis was writing scripts to /tmp with default permissions (0o644), exposing the API key to other local users. Switch to tempfile.mkstemp + chmod 0o600, matching the single-analysis pattern. Also fix cancel_task cleanup to use glob patterns for tempfile-generated paths. Co-Authored-By: Claude Opus 4.6 --- web_dashboard/backend/main.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/web_dashboard/backend/main.py b/web_dashboard/backend/main.py index 13578465..7e922298 100644 --- a/web_dashboard/backend/main.py +++ b/web_dashboard/backend/main.py @@ -457,12 +457,12 @@ async def cancel_task(task_id: str): _save_task_status(task_id, app.state.task_results[task_id]) await broadcast_progress(task_id, app.state.task_results[task_id]) - # Clean up temp script - script_path = Path(f"/tmp/analysis_{task_id}.py") - try: - script_path.unlink() - except Exception: - pass + # Clean up temp script (may use tempfile.mkstemp with random suffix) + for p in Path("/tmp").glob(f"analysis_{task_id}_*.py"): + try: + p.unlink() + except Exception: + pass # Remove persisted task state _delete_task_status(task_id) @@ -874,6 +874,12 @@ async def start_portfolio_analysis(): clean_env["ANTHROPIC_API_KEY"] = api_key clean_env["ANTHROPIC_BASE_URL"] = "https://api.minimaxi.com/anthropic" + fd, script_path_str = tempfile.mkstemp(suffix=".py", prefix=f"analysis_{task_id}_{i}_") + script_path = Path(script_path_str) + os.chmod(script_path, 0o600) + with os.fdopen(fd, "w") as f: + f.write(ANALYSIS_SCRIPT_TEMPLATE) + proc = await asyncio.create_subprocess_exec( str(ANALYSIS_PYTHON), str(script_path), ticker, date, str(REPO_ROOT), stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE,