Skip to content

feat(mcp): component_mcp column masking (Phase 5) - #261

Open
askdba wants to merge 1 commit into
mainfrom
feat/mcp-mask-columns
Open

askdba wants to merge 1 commit into
mainfrom
feat/mcp-mask-columns

Conversation

@askdba

@askdba askdba commented Nov 2, 2026

Copy link
Copy Markdown
Owner

Phase 5 item from #256: column masking.

RFC 0001 listed masking as a parity gap with mysql-mcp-server's MYSQL_MCP_MASK_COLUMNS. Until it was ported, the RFC required the endpoint to disable run_query whenever masking was configured. Porting it is small, so this PR ports it rather than disabling run_query.

Change

  • New mcp_http.mask_columns setting: read-only, comma-separated patterns, none by default.
  • It follows Go's maskResults (cmd/mysql-mcp-server/tools.go):
    • patterns are trimmed, and empty ones are ignored;
    • a result column whose name contains a pattern (case-insensitive) is masked;
    • each non-NULL value in a masked column becomes "********", and NULL stays null.
  • Binary values that would otherwise be {"base64": ...} are masked too.
  • It applies to every result run_as() builds, including the tool pack's CALL.
  • Same caveat as the Go server: it matches result column names, so an alias bypasses it. The docs say to use grants or views for data an account must not see.

Tests

scripts/test-mcp-endpoint.sh on mysql:26.10.0: 33 passed, 0 failed. With mask_columns = ' secret, PASS ,,':

  • user_password and SecretKey are masked;
  • secret_null stays null;
  • ok is unchanged;
  • a binary pass_hash is masked.

Docs: settings table, CHANGELOG. The RFC's parity note gets updated in mysql-mcp-server when Phase 5 lands.

Independent of #257–#260.

Part of #256.

🤖 Generated with Claude Code

Ports mysql-mcp-server's MYSQL_MCP_MASK_COLUMNS rules: a result column
whose name contains one of the comma-separated patterns (ASCII
case-insensitive, empty patterns ignored) has every non-NULL value replaced
by "********". RFC 0001 listed masking as a parity gap and required the
endpoint to disable run_query while it is set; with the port, the same
setting gives the same output on both servers.

test-mcp-endpoint.sh: masked, unmasked, NULL and binary values, with
spaced and mixed-case patterns. 33 checks.

Part of #256 (RFC 0001 Phase 5).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Nov 2, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 45 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 1ad40f1f-3b1d-4868-ac80-e3517b7a1641
Commits

Reviewing files that changed from the base of the PR and between ff59fea and a166976.

Files selected for processing: 4
  • CHANGELOG.md
  • docs/MCP_COMPONENTS.md
  • scripts/test-mcp-endpoint.sh
  • src/mcp/endpoint/component_mcp.cc
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-02T10:10:57.377673Z a166976 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a166976f8f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

constexpr char kMasked[] = "********";

std::string ascii_lower(std::string s) {
for (char &c : s) c = static_cast<char>(std::tolower(static_cast<unsigned char>(c)));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Match Go's Unicode case-folding behavior

When a result column name and mask pattern differ only by non-ASCII case (for example, ПАРОЛЬ and пароль), this byte-wise std::tolower does not case-fold the UTF-8 characters, so the value is returned unmasked. The Go implementation uses strings.ToLower on both sides and masks this case, so this breaks the stated parity and can expose a sensitive column; use Unicode-aware folding or narrow the parity claim. Go maskResults

Useful? React with 👍 / 👎.

This branch has not been deployed

No deployments
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