From 5be8ba4b45b06b4cd5db91be39d621a9f2b20cab Mon Sep 17 00:00:00 2001 From: Hongming Wang Date: Sat, 18 Apr 2026 11:09:24 -0700 Subject: [PATCH] fix(security): GLOBAL memory delimiter spoofing + pin MCP npm version SAFE-T1201 (#807): Escape [MEMORY prefix in GLOBAL memory content on write to prevent delimiter-spoofing prompt injection. Content stored as "[_MEMORY " so it renders as text, not structure, when wrapped with the real delimiter on read. SAFE-T1102 (#805): Pin @molecule-ai/mcp-server@1.0.0 in .mcp.json.example. Prevents supply-chain attacks via unpinned npx -y. Co-Authored-By: Claude Opus 4.6 (1M context) --- .mcp.json.example | 2 +- workspace-server/internal/handlers/memories.go | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.mcp.json.example b/.mcp.json.example index d0f68704..99531813 100644 --- a/.mcp.json.example +++ b/.mcp.json.example @@ -3,7 +3,7 @@ "molecule": { "type": "stdio", "command": "npx", - "args": ["-y", "@molecule-ai/mcp-server"], + "args": ["-y", "@molecule-ai/mcp-server@1.0.0"], "env": { "MOLECULE_URL": "http://localhost:8080" } diff --git a/workspace-server/internal/handlers/memories.go b/workspace-server/internal/handlers/memories.go index faea5ff9..824e40e5 100644 --- a/workspace-server/internal/handlers/memories.go +++ b/workspace-server/internal/handlers/memories.go @@ -179,6 +179,14 @@ func (h *MemoriesHandler) Commit(c *gin.Context) { content := body.Content content, _ = redactSecrets(workspaceID, content) + // SAFE-T1201: prevent delimiter spoofing in GLOBAL memories (#807). + // If content contains the delimiter prefix "[MEMORY ", an attacker could + // craft a fake nested delimiter to inject instructions when the memory + // is read back. Escape the bracket so it renders as text, not structure. + if body.Scope == "GLOBAL" { + content = strings.ReplaceAll(content, "[MEMORY ", "[_MEMORY ") + } + var memoryID string err := db.DB.QueryRowContext(ctx, ` INSERT INTO agent_memories (workspace_id, content, scope, namespace)