Remove KQL management-command blocklist from shared KqlQueryValidator (Kusto + Monitor)
- Dominant language
- C#
- Stars
- 3.7k
- Forks
- 624
- Avg merge
- 2d 20h
- Merged PRs (30d)
- 220
Description
## Background
In #3202 the MySQL and PostgreSQL `database query` tools were marked `Destructive = true`, `Idempotent = false`, `ReadOnly = false`, and the keyword/verb blocklists were removed from their validators. The rationale: the signed-in user's permissions are the authority on what a statement may do, and heuristic blocklists produce false positives on legitimate queries while being trivially bypassable.
`KqlQueryValidator` should get the same treatment.
## Current behavior
`core/Microsoft.Mcp.Core/src/Validation/KqlQueryValidator.cs` is shared by two toolsets:
- `kusto query` — `KustoService.cs:254`
- Monitor — `MonitorService.QueryResourceLogs` (:54), `QueryWorkspace` (:113), `QueryWorkspaceLogs` (:247), backing `monitor_workspace_log_query`, `monitor_resource_log_query`, and related commands
It rejects queries based on:
- **`s_dangerousCommands` blocklist** — `.drop`, `.alter`, `.create`, `.delete`, `.set`, `.append`, `.set-or-append`, `.set-or-replace`, `.ingest`, `.purge`, `.execute`, matched at input start or after `|` / `;`. These are Kusto *management/control commands*; whether a caller may run them is already governed by their Kusto RBAC role (Database Admin/Ingestor vs Viewer).
- **Tautology detection** — `s_tautologyPattern` rejects `or 1==1`, `or 1=1`, `or true`, `or 'x'=='x'`. These are legitimate constructs in a query the caller authored themselves; there is no untrusted concatenation happening here. This also false-positives on any `where` clause that happens to match the shape.
## Proposed change
Reduce `KqlQueryValidator` to structural checks only:
- Empty / whitespace-only query
- Max query length (currently 10,000 chars)
Remove `s_dangerousCommands`, `s_managementCommandPattern`, `BuildManagementCommandPattern()`, and `s_tautologyPattern`. At that point the string-literal stripping (`queryWithoutStrings`) has no remaining consumer and can go too.
## Considerations
- This validator lives in `Microsoft.Mcp.Core` and is **shared across two toolsets** — changing it affects Kusto and Monitor together. Decide whether both should be relaxed in one change or whether the validator should become configurable per caller.
- If management commands become reachable through `kusto query`, revisit `QueryCommand`'s metadata (`Destructive` / `ReadOnly`) the way #3202 did for MySQL/PostgreSQL. The Monitor log query commands query Log Analytics rather than ADX and may warrant different treatment.
## Checklist
- [ ] Decide on shared vs. per-caller validation policy for Kusto and Monitor
- [ ] Trim `KqlQueryValidator` to structural checks
- [ ] Update `core/Microsoft.Mcp.Core/tests/Microsoft.Mcp.Core.Tests/Validation/KqlQueryValidatorTests.cs`
- [ ] Update affected command metadata if management commands become reachable
- [ ] Update `servers/Azure.Mcp.Server/docs/azmcp-commands.md` if descriptions or metadata flags change
- [ ] Add a changelog entry under `servers/Azure.Mcp.Server/changelog-entries/` (`.yml`, not `.md` — `Compile-Changelog.ps1` only globs `*.yaml`/`*.yml`)
Contributor guide
Assessment
This issue has not been assessed yet.