From 042989a96add96750504cfd79a7c73038ef12094 Mon Sep 17 00:00:00 2001 From: Hayden Garvey <154503486+groupthinking@users.noreply.github.com> Date: Sun, 30 Aug 2026 23:11:01 +0000 Subject: [PATCH] fix(security): serialize Mojo shared-memory payloads as JSON, not pickle Removes the last pickle serialization in production code. Pickle bytes in a cross-process shared-memory segment force the receiver into pickle.loads, the same RCE pattern REM-001 removed from the Redis cache. Generated with [Linear](https://linear.app/myxstack/issue/GRV-423/addressing-issues#agent-session-1060aec4) Co-authored-by: linear-code[bot] <222613912+linear-code[bot]@users.noreply.github.com> --- .../unified/mcp_a2a_mojo_integration.py | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/agents/unified/mcp_a2a_mojo_integration.py b/src/agents/unified/mcp_a2a_mojo_integration.py index 98ce1a99e..a2998c949 100644 --- a/src/agents/unified/mcp_a2a_mojo_integration.py +++ b/src/agents/unified/mcp_a2a_mojo_integration.py @@ -165,8 +165,8 @@ def select_optimal_transport( return TransportStrategy.SHARED_MEMORY +import json import multiprocessing -import pickle import struct from multiprocessing import shared_memory @@ -230,10 +230,20 @@ async def _zero_copy_send(self, message: UnifiedMessage) -> dict[str, Any]: async def _shared_memory_send(self, message: UnifiedMessage) -> dict[str, Any]: """Shared memory for large transfers""" try: - # Serialize the message - # Note: In a real full implementation, we'd handle the pickling more carefully - # to avoid serializing the whole object if we only want parts. - serialized = pickle.dumps(message) + # SECURITY: serialize as JSON, not pickle — shared memory is a + # cross-process medium, and a pickle payload there forces the + # receiver into pickle.loads (arbitrary code execution if the + # segment is ever writable by a less-trusted process). + serialized = json.dumps( + { + "a2a_message": message.a2a_message.to_dict(), + "mcp_context": message.mcp_context.to_dict(), + "transport_strategy": message.transport_strategy.value, + "priority": message.priority, + "deadline_ms": message.deadline_ms, + }, + default=str, + ).encode("utf-8") size = len(serialized) # Create or get shared memory block