Skip to content

test(mcp): security suite for the MCP server - #1142

Merged
ZhuchkaTriplesix merged 2 commits into
devfrom
issue/1138-mcp-security-tests
Oct 8, 2026
Merged

ZhuchkaTriplesix merged 2 commits into
devfrom
issue/1138-mcp-security-tests

Conversation

@ZhuchkaTriplesix

Copy link
Copy Markdown
Member

Security suite for the MCP epic #1133, with two hardening fixes it turned up.

Fixes

  • Credentials in error messages. Driver errors can quote a connection string, an option list or a key. Every tool error (and internal errors) now goes through McpRedaction: the connection's own secrets when loaded (password, connection string, SSH password / key / passphrase), scheme://user:pass@ user info, password= / pwd= / passphrase= / token= / api_key= values and PEM private keys are masked. Also applied when creating the delegate fails.
  • MySQL executable comments. MySQL / MariaDB run the body of /*! ... */ and /*M! ... */, which the comment stripper hid from the guard. For MySQL connections such comments are now refused.

Tests (test/core/mcp/mcp_security_test.dart)

  • ~70 write forms across Postgres / MySQL / SQLite are refused by McpSqlGuard (DML, DDL, GRANT, COPY, CALL, DO, PREPARE/EXECUTE, SET / RESET / BEGIN READ WRITE, NOTIFY, stacked statements, data-modifying CTEs, EXPLAIN ANALYZE, SELECT INTO / INTO OUTFILE, row locks, server functions, comment-split keywords, executable comments, ATTACH, writable PRAGMAs, load_extension ...), and none of them reaches the delegate through run_query or explain_query.
  • The production delegates are always created with isReadOnly: true (layer 2).
  • Every tool and the schema:// resource, called through a real MCP client, never return password, SSH password / key / passphrase, host, user or file path: in normal results, in driver errors that quote all of them, and when delegate creation fails.
  • A connection that is not shared is invisible to every tool and the resource, and no delegate is ever created for it.
  • McpRedaction unit tests.

Already covered elsewhere and not duplicated: token refusal and 0600 / 0700 permissions (mcp_server_test.dart), timeout / row limit / cell truncation (mcp_query_service_test.dart), the database refusing a write on the real SQLite MCP session (mcp_sqlite_readonly_test.dart).

Not done: a live Postgres / MySQL read-only check; CI has no database services. The session flags themselves are covered by the pool tests.

Written without running locally; CI is the first run.

Closes #1138

@github-actions github-actions Bot added tests Theme parser epic core Core library logic and services P2 Medium priority / Parity & Refactoring labels Oct 8, 2026
@ZhuchkaTriplesix
ZhuchkaTriplesix merged commit e9235f1 into dev Oct 8, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core Core library logic and services P2 Medium priority / Parity & Refactoring tests Theme parser epic

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant