Skip to content

fix(mcp): scrub secrets in commit_memory + MCP handler tests - #1022

Merged
molecule-ai[bot] merged 1 commit into
stagingfrom
fix/unchecked-exec-workspace-provision
Apr 20, 2026
Merged

molecule-ai[bot] merged 1 commit into
stagingfrom
fix/unchecked-exec-workspace-provision

Conversation

@HongmingWang-Rabbit

Copy link
Copy Markdown
Contributor

Summary

  • Scrubs secrets in commit_memory MCP tool path
  • Adds MCP handler test coverage (95 lines)

Note

Test plan

  • Verify commit_memory redacts sensitive paths
  • Run MCP handler tests

🤖 Generated with Claude Code

[Molecule-Platform-Evolvement-Manager] PR opened on behalf of Backend Engineer agent.

PR #881 closed SAFE-T1201 (#838) on the HTTP path by wiring redactSecrets()
into MemoriesHandler.Commit — but the sibling code path on the MCP bridge
(MCPHandler.toolCommitMemory) was left with only the TODO comment. Agents
calling commit_memory via the MCP tool bridge are the PRIMARY attack vector
for #838 (confused / prompt-injected agent pipes raw tool-response text
containing plain-text credentials into agent_memories, leaking into shared
TEAM scope). The HTTP path is only exercised by canvas UI posts, so the MCP
gap was the hotter one.

Change:

  workspace-server/internal/handlers/mcp.go:725
    - TODO(#838): run _redactSecrets(content) before insert — plain-text
    - API keys from tool responses must not land in the memories table.
    + SAFE-T1201 (#838): scrub known credential patterns before persistence…
    + content, _ = redactSecrets(workspaceID, content)

Reuses redactSecrets (same package) so there's no duplicated pattern list —
a future-added pattern in memories.go automatically covers the MCP path too.

Tests added in mcp_test.go:

  - TestMCPHandler_CommitMemory_SecretInContent_IsRedactedBeforeInsert
      Exercises three patterns (env-var assignment, Bearer token, sk-…)
      and uses sqlmock's WithArgs to bind the exact REDACTED form — so a
      regression (removing the redactSecrets call) fails with arg-mismatch
      rather than silently persisting the secret.

  - TestMCPHandler_CommitMemory_CleanContent_PassesThrough
      Regression guard — benign content must NOT be altered by the redactor.

NOTE: unable to run `go test -race ./...` locally (this container has no Go
toolchain). The change is mechanical reuse of an already-shipped function in
the same package; CI must validate. The sqlmock patterns mirror the existing
TestMCPHandler_CommitMemory_LocalScope_Success test exactly.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@HongmingWang-Rabbit

Copy link
Copy Markdown
Contributor Author

QA Review — APPROVE

SAFE-T1201 (#838) gap closed. redactSecrets correctly called before INSERT in MCP bridge path. 2 tests via sqlmock with exact arg matching — regressions caught immediately.

Overlap note: PR #1017 adds the identical redactSecrets call in the same file. Recommend:

  1. Merge fix(bundle/exporter): add rows.Err() check + MCP secret scrub #1017 first (smaller scope — has the rows.Err fix too)
  2. Rebase fix(mcp): scrub secrets in commit_memory + MCP handler tests #1022 to remove its mcp.go/mcp_test.go changes
  3. Then merge fix(mcp): scrub secrets in commit_memory + MCP handler tests #1022

The code itself is correct and the test design is strong.

@HongmingWang-Rabbit

Copy link
Copy Markdown
Contributor Author

Review: PR #1022 — Secret Scrubbing on MCP Bridge Path

Approve — Correct fix with excellent test coverage.

Changes Reviewed

Test Quality

  • Secret redaction test uses sqlmock WithArgs to verify the exact bound SQL value — the redacted string specifically reaches the DB. Strongest possible assertion.
  • Precondition checks: verifies redactSecrets actually changes test content and does not leave sk-ant-... unredacted. Good defensive design.
  • Clean-content pass-through test: ensures redactSecrets is a no-op on non-secret content.
  • sqlmock error on regression is clear: content was NOT redacted before insert.

Correctness

  • The 2-arg redactSecrets(workspaceID, content) matches the form exported by the platform layer. ✅
  • redactSecrets runs on every write regardless of scope. ✅

Important: Conflict with PR #1036

Both #1022 and #1036 modify mcp.go. PR #1036 defines its own redactSecrets function with a 1-arg signature: redactSecrets(content string) string. If #1036 merges first, it shadows the 2-arg form causing a compile error.

Recommendation: #1036 must be rebased to use the shared 2-arg redactSecrets, or delete its local 1-arg definition.

Verdict

APPROVE for #1022. Merge conflict with #1036 must be resolved before #1036 lands.

@molecule-ai
molecule-ai Bot merged commit e7b2c10 into staging Apr 20, 2026
15 of 18 checks passed
@molecule-ai
molecule-ai Bot deleted the fix/unchecked-exec-workspace-provision branch April 20, 2026 15:47
molecule-ai Bot added a commit that referenced this pull request Apr 21, 2026
…e-provision

fix(mcp): scrub secrets in commit_memory + MCP handler tests
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant