From 7c2e31cbe5eae11bfa3103b8cb55ab0a46e962d8 Mon Sep 17 00:00:00 2001 From: 134 Date: Tue, 23 Jun 2026 21:06:55 +0800 Subject: [PATCH] fix: reject mismatched canvas agent project ids --- lib/canvas/agent-operation-route.ts | 11 ++++++++ tests/routes/canvas-agent-operations.test.ts | 29 ++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/lib/canvas/agent-operation-route.ts b/lib/canvas/agent-operation-route.ts index 5a6408e0e..99edab38f 100644 --- a/lib/canvas/agent-operation-route.ts +++ b/lib/canvas/agent-operation-route.ts @@ -64,6 +64,17 @@ export async function handleCanvasAgentOperationRouteRequest(params: { try { const rawBody = params.readBody ? await params.readBody() : params.rawBody; const body = parseCanvasAgentOperationRequestBody(rawBody); + const planProjectId = String(body.operationPlan.projectId || "").trim(); + if (planProjectId && planProjectId !== params.projectId) { + return { + status: 400, + body: { + success: false, + error: "operation projectId 与请求项目不一致", + code: "CANVAS_AGENT_PROJECT_MISMATCH", + }, + }; + } const result = await params.applyOperation({ userId, projectId: params.projectId, diff --git a/tests/routes/canvas-agent-operations.test.ts b/tests/routes/canvas-agent-operations.test.ts index b5878891b..031bbb4d8 100644 --- a/tests/routes/canvas-agent-operations.test.ts +++ b/tests/routes/canvas-agent-operations.test.ts @@ -428,6 +428,35 @@ test.describe("canvas agent operation route handler", () => { ]); }); + test("rejects operation plans for a different project before applying", async () => { + let operationApplied = false; + + const response = await handleCanvasAgentOperationRouteRequest({ + userId: "user-1", + projectId, + rawBody: buildRouteRequestBody({ + projectId: "33333333-3333-4333-8333-333333333333", + operation: "insert_beside", + anchorNodeId: "image-1", + mediaItems: [buildMediaItem(1)], + }), + features: enabledRouteFeatures, + applyOperation: async () => { + operationApplied = true; + return buildRouteSuccessResult(); + }, + }); + + expect(response).toMatchObject({ + status: 400, + body: { + success: false, + code: "CANVAS_AGENT_PROJECT_MISMATCH", + }, + }); + expect(operationApplied).toBe(false); + }); + test("maps invalid bodies and mutation errors to API responses", async () => { let operationApplied = false; const invalidResponse = await handleCanvasAgentOperationRouteRequest({