From 103cc20ae2fcc346e2994cbdf4a3a70cb56dcc1d Mon Sep 17 00:00:00 2001 From: Jordan Frazier Date: Mon, 8 Jun 2026 18:57:08 -0400 Subject: [PATCH] fix(security): pin watsonx orchestrate run target to the deployment resource key build_orchestrate_run_payload resolved the run's agent_id as provider_data.get("agent_id") or deployment_id. The caller-supplied branch is dead today (the API input slot WatsonxApiExecutionInput is extra="forbid" and has no agent_id field), so it always fell back to deployment_id. Drop the dead fallback and pin agent_id to the deployment's own owner-controlled resource key so a future caller that bypasses the input slot cannot redirect the run to an arbitrary agent in the owner's WxO tenant. Defense-in-depth; no behavior change. --- .../deployment/watsonx_orchestrate/core/execution.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/backend/base/langflow/services/adapters/deployment/watsonx_orchestrate/core/execution.py b/src/backend/base/langflow/services/adapters/deployment/watsonx_orchestrate/core/execution.py index 56ed8679cd..c65a30ce01 100644 --- a/src/backend/base/langflow/services/adapters/deployment/watsonx_orchestrate/core/execution.py +++ b/src/backend/base/langflow/services/adapters/deployment/watsonx_orchestrate/core/execution.py @@ -26,7 +26,11 @@ def build_orchestrate_run_payload( payload: dict[str, Any] = { "message": message_payload, - "agent_id": str(provider_data.get("agent_id") or deployment_id), + # The run target is always the deployment's own (owner-pinned) resource key. Do NOT honor a + # caller-supplied provider_data["agent_id"]: the API input slot (WatsonxApiExecutionInput) is + # extra="forbid" so it can't arrive today, and reading it here would let a future caller that + # bypasses the slot redirect the run to an arbitrary agent in the owner's WxO tenant. + "agent_id": str(deployment_id), } thread_id = provider_data.get("thread_id")