From f0a751ca90fd4e4cd141ac55924f34dfccf0df1b Mon Sep 17 00:00:00 2001 From: Molecule AI Core-BE Date: Tue, 12 May 2026 07:34:23 +0000 Subject: [PATCH] =?UTF-8?q?test(handlers/mcp):=20harden=20RecallMemory=5FG?= =?UTF-8?q?lobalScope=20test=20=E2=80=94=20assert=20OFFSEC-001=20scrub=20c?= =?UTF-8?q?ontract=20(mc#681)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../internal/handlers/mcp_test.go | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/workspace-server/internal/handlers/mcp_test.go b/workspace-server/internal/handlers/mcp_test.go index dbad430a..ecb0c12a 100644 --- a/workspace-server/internal/handlers/mcp_test.go +++ b/workspace-server/internal/handlers/mcp_test.go @@ -9,6 +9,7 @@ import ( "net/http" "net/http/httptest" "os" + "strings" "testing" "errors" @@ -536,7 +537,12 @@ func TestMCPHandler_CommitMemory_CleanContent_PassesThrough(t *testing.T) { // tools/call — recall_memory // ───────────────────────────────────────────────────────────────────────────── -func TestMCPHandler_RecallMemory_GlobalScope_Blocked(t *testing.T) { +// TestMCPHandler_RecallMemory_GlobalScope_ScrubsInternalError verifies C3 is +// enforced and the OFFSEC-001 scrub contract is applied. The tool returns a +// descriptive error mentioning GLOBAL scope; dispatchRPC must replace it with +// a constant "tool call failed" message so internal implementation details +// never reach the caller. +func TestMCPHandler_RecallMemory_GlobalScope_ScrubsInternalError(t *testing.T) { h, mock := newMCPHandler(t) // No DB expectations — handler must abort before touching the DB. @@ -556,7 +562,20 @@ func TestMCPHandler_RecallMemory_GlobalScope_Blocked(t *testing.T) { var resp mcpResponse json.Unmarshal(w.Body.Bytes(), &resp) if resp.Error == nil { - t.Error("expected JSON-RPC error for GLOBAL scope recall, got nil") + t.Fatal("expected JSON-RPC error for GLOBAL scope recall, got nil") + } + // OFFSEC-001 scrub contract: error code is -32000 (server error). + if resp.Error.Code != -32000 { + t.Errorf("expected error code -32000, got %d", resp.Error.Code) + } + // Message must be the constant scrubbed string — no "GLOBAL" or bridge + // implementation details leaked to the caller. + if resp.Error.Message != "tool call failed" { + t.Errorf("error message should be constant 'tool call failed', got: %q", resp.Error.Message) + } + // Defence-in-depth: the original error body must not appear in the response. + if strings.Contains(resp.Error.Message, "GLOBAL") || strings.Contains(resp.Error.Message, "bridge") { + t.Error("scrubbed error message must not contain original error keywords") } if err := mock.ExpectationsWereMet(); err != nil { t.Errorf("unexpected DB calls on GLOBAL scope block: %v", err)