From bbb2f1b847243f03002a24c92236581f9f983624 Mon Sep 17 00:00:00 2001 From: "molecule-ai[bot]" <276602405+molecule-ai[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 22:13:55 +0000 Subject: [PATCH] fix(mcp): add TODO(#838) in toolCommitMemory + document X-Workspace-ID trust in toolDelegateTask Security Auditor pre-merge conditions for PR#840: C5: toolCommitMemory passes content directly to DB insert without secret redaction. Gap is tracked to #838 (platform-wide _redactSecrets pass). Adds inline TODO(#838) comment at the insert site so the gap is visible in-code, not only in the issue tracker. C6: toolDelegateTask sets X-Workspace-ID but no bearer token on the outbound A2A call. The /workspaces/:id/a2a route is intentionally outside WorkspaceAuth (by design in router.go). CanCommunicate is enforced before the request is constructed, and callerID was authenticated by WorkspaceAuth on the MCP bridge entry point. Documents this trust assumption at the call site. --- platform/internal/handlers/mcp.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/platform/internal/handlers/mcp.go b/platform/internal/handlers/mcp.go index a77a6eb1..f036f534 100644 --- a/platform/internal/handlers/mcp.go +++ b/platform/internal/handlers/mcp.go @@ -548,6 +548,12 @@ func (h *MCPHandler) toolDelegateTask(ctx context.Context, callerID string, args return "", fmt.Errorf("failed to create request: %w", err) } httpReq.Header.Set("Content-Type", "application/json") + // X-Workspace-ID identifies this caller to the A2A proxy. The /workspaces/:id/a2a + // endpoint is intentionally outside WorkspaceAuth (agents do not hold bearer tokens + // to peer workspaces). Access control is enforced by CanCommunicate above, which + // already validated callerID → targetID before this request is constructed. + // callerID was authenticated by WorkspaceAuth on the MCP bridge entry point, + // so this header reflects a verified caller identity, not a spoofable value. httpReq.Header.Set("X-Workspace-ID", callerID) resp, err := http.DefaultClient.Do(httpReq) @@ -717,6 +723,8 @@ func (h *MCPHandler) toolCommitMemory(ctx context.Context, workspaceID string, a } memoryID := uuid.New().String() + // TODO(#838): run _redactSecrets(content) before insert — plain-text API keys + // from tool responses must not land in the memories table. _, err := h.database.ExecContext(ctx, ` INSERT INTO agent_memories (id, workspace_id, content, scope, namespace) VALUES ($1, $2, $3, $4, $5)