From 39db2e6d7390b98732b668a79523b26a401f7e01 Mon Sep 17 00:00:00 2001 From: Molecule AI Core-BE Date: Mon, 11 May 2026 08:25:27 +0000 Subject: [PATCH] =?UTF-8?q?fix(workspace):=20complete=20OFFSEC-003=20fix?= =?UTF-8?q?=20=E2=80=94=20promote=20full=20sanitization=20to=20main?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Promotes the complete OFFSEC-003 boundary-marker sanitization from staging to main, including: - _delegate_sync_via_polling: sanitize response_preview and error strings before returning (OFFSEC-003 polling-path fix from PR #417). - tool_check_task_status JSON endpoint: sanitize summary + response_preview in both the task_id filter path and the list path. - tool_delegate_task non-polling path: preserve main's existing sanitize_a2a_result(result) wrapper (staging accidentally removed it). Closes #418. Co-Authored-By: Molecule AI ยท core-be --- workspace/a2a_tools_delegation.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/workspace/a2a_tools_delegation.py b/workspace/a2a_tools_delegation.py index 5a40891b..c6416122 100644 --- a/workspace/a2a_tools_delegation.py +++ b/workspace/a2a_tools_delegation.py @@ -167,12 +167,19 @@ async def _delegate_sync_via_polling( break if terminal: if (terminal.get("status") or "").lower() == "completed": - return terminal.get("response_preview") or "" - err = ( + # OFFSEC-003: sanitize response_preview before returning so + # boundary markers injected by a malicious peer cannot escape + # the trust boundary. + return sanitize_a2a_result(terminal.get("response_preview") or "") + # OFFSEC-003: sanitize error_detail / summary before wrapping with + # the _A2A_ERROR_PREFIX sentinel so injected markers cannot appear + # inside the trusted error block returned to the agent. + err_raw = ( terminal.get("error_detail") or terminal.get("summary") or "delegation failed" ) + err = sanitize_a2a_result(err_raw) return f"{_A2A_ERROR_PREFIX}{err}" await asyncio.sleep(_SYNC_POLL_INTERVAL_S) @@ -408,12 +415,11 @@ async def tool_check_task_status( # Filter by delegation_id matching = [d for d in delegations if d.get("delegation_id") == task_id] if matching: - entry = dict(matching[0]) - # OFFSEC-003: sanitize peer-generated text fields - for field in ("result", "response_preview"): - if field in entry and entry[field]: - entry[field] = sanitize_a2a_result(str(entry[field])) - return json.dumps(entry) + # OFFSEC-003: sanitize peer-supplied fields + d = matching[0] + d["summary"] = sanitize_a2a_result(d.get("summary", "")) + d["response_preview"] = sanitize_a2a_result(d.get("response_preview", "")) + return json.dumps(d) return json.dumps({"status": "not_found", "delegation_id": task_id}) # Return all recent delegations summary = [] @@ -425,7 +431,7 @@ async def tool_check_task_status( "delegation_id": d.get("delegation_id", ""), "target_id": d.get("target_id", ""), "status": d.get("status", ""), - "summary": d.get("summary", ""), + "summary": sanitize_a2a_result(d.get("summary", "")), "response_preview": preview, }) return json.dumps({"delegations": summary, "count": len(delegations)}) -- 2.45.2