Skip to content

[Kusto] Add AZURE_MCP_DANGEROUSLY_ALLOW_ADDITIONAL_KUSTO_HOSTS env var for internal proxies#2534

Open
tloula wants to merge 3 commits intomicrosoft:mainfrom
tloula:developer/trevorloula/kusto-additional-trusted-hosts
Open

[Kusto] Add AZURE_MCP_DANGEROUSLY_ALLOW_ADDITIONAL_KUSTO_HOSTS env var for internal proxies#2534
tloula wants to merge 3 commits intomicrosoft:mainfrom
tloula:developer/trevorloula/kusto-additional-trusted-hosts

Conversation

@tloula
Copy link
Copy Markdown

@tloula tloula commented Apr 29, 2026

Summary

Adds an opt-in environment variable AZURE_MCP_DANGEROUSLY_ALLOW_ADDITIONAL_KUSTO_HOSTS (comma-separated hostnames) that extends the Kusto SSRF allowlist to include user-specified hosts. This unblocks scenarios where Kusto queries need to be routed through internal proxies (e.g., a regional fan-out proxy hosted on *.azurewebsites.net) without disabling SSRF protections globally.

Motivation

Our team runs an internal multi-region Kusto proxy that routes queries to the appropriate regional cluster based on context. The Kusto desktop and web explorers support adding trusted hosts via UI, but the Azure MCP server rejects any host outside *.kusto.windows.net / *.kustomfa.windows.net / *.kusto.azuresynapse.net, with no way to override.

Design

  • New const AdditionalTrustedHostsEnvVarName in KustoClient.cs.
  • IsValidKustoHost now also accepts hosts present in the env var (case-insensitive, trimmed).
  • Naming follows existing AZURE_MCP_DANGEROUSLY_* precedent (DISABLE_HTTPS_REDIRECTION, ENABLE_FORWARDED_HEADERS).
  • Default behavior is unchanged — variable must be explicitly set.

Changes

  • tools/Azure.Mcp.Tools.Kusto/src/Services/KustoClient.cs — env var support.
  • tools/Azure.Mcp.Tools.Kusto/tests/.../KustoClientTests.cs — 6 new tests.
  • servers/Azure.Mcp.Server/TROUBLESHOOTING.md — new troubleshooting section.
  • servers/Azure.Mcp.Server/changelog-entries/1777483696796.yaml — Features Added entry.
  • core/.../ClearEnvironmentVariablesBeforeTestAttribute.cs — env cleanup for tests.

Validation

  • 70/70 unit tests pass (Azure.Mcp.Tools.Kusto.UnitTests).
  • cspell clean.
  • Locally built azmcp.exe confirmed working against an internal proxy with the variable set.

Invoking Livetests

Copilot submitted PRs are not trustworthy by default. Users with write access to the repo need to validate the contents of this PR before leaving a comment with the text /azp run mcp - pullrequest - live. This will trigger the necessary livetest workflows to complete required validation.

…for additional trusted hostnames

Allows callers to route Kusto queries through internal proxies (e.g., a regional fan-out proxy hosted on *.azurewebsites.net) without disabling SSRF protections globally. Modeled on existing AZURE_MCP_DANGEROUSLY_DISABLE_HTTPS_REDIRECTION and AZURE_MCP_DANGEROUSLY_ENABLE_FORWARDED_HEADERS env vars.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 29, 2026 17:38
@tloula tloula requested review from a team, danield137 and prvavill as code owners April 29, 2026 17:38
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds an opt-in environment variable (AZURE_MCP_DANGEROUSLY_ALLOW_ADDITIONAL_KUSTO_HOSTS) to extend the Kusto SSRF allowlist with explicitly configured hostnames, enabling routing through internal proxies without disabling SSRF protections globally.

Changes:

  • Added env-var-based additional trusted-host validation in KustoClient host allowlist logic.
  • Added unit tests covering env var presence, parsing, and case-insensitive matching.
  • Documented troubleshooting guidance and added a changelog entry; ensured test env cleanup includes the new variable.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tools/Azure.Mcp.Tools.Kusto/src/Services/KustoClient.cs Implements env-var parsing and host matching to extend SSRF allowlist
tools/Azure.Mcp.Tools.Kusto/tests/Azure.Mcp.Tools.Kusto.UnitTests/KustoClientTests.cs Adds unit tests validating behavior with/without env var and parsing edge cases
servers/Azure.Mcp.Server/TROUBLESHOOTING.md Documents how to use the env var and warns about SSRF/token risks
servers/Azure.Mcp.Server/changelog-entries/1777483696796.yaml Records the new env var feature in changelog format
core/Microsoft.Mcp.Core/tests/Microsoft.Mcp.Tests/Helpers/ClearEnvironmentVariablesBeforeTestAttribute.cs Adds new env var to test-time environment cleanup list
Comment thread tools/Azure.Mcp.Tools.Kusto/src/Services/KustoClient.cs
@github-actions
Copy link
Copy Markdown

Thank you for your contribution @tloula! We will review the pull request and get back to you soon.

Copy link
Copy Markdown
Contributor

@jongio jongio left a comment

Choose a reason for hiding this comment

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

Follows the existing AZURE_MCP_DANGEROUSLY_* convention well. Tests cover the key scenarios (set/unset, comma-separated, case-insensitive, HTTP rejection), and the TROUBLESHOOTING doc update includes a clear security warning.

One thing to flag: GetKustoScope() determines the token audience by inspecting the cluster hostname suffix. Custom proxy hostnames (e.g., kusto-proxy.example.com) won't match any sovereign cloud suffix, so the token always targets the public cloud Kusto endpoint (kusto.kusto.windows.net/.default). This is fine for proxies routing to public cloud clusters but would silently produce the wrong token if someone routes through a proxy to a sovereign cloud (China/US Gov) cluster. Worth a note in the troubleshooting section, or a follow-up to support a scope override env var.

Comment thread tools/Azure.Mcp.Tools.Kusto/src/Services/KustoClient.cs
Copy link
Copy Markdown
Contributor

@jongio jongio left a comment

Choose a reason for hiding this comment

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

Addresses my previous feedback. The loopback/IP literal guard is the right approach - IPAddress.TryParse catches all literals, and the check runs before the env var read. Troubleshooting note for sovereign scope is clear. Looks good.

@github-project-automation github-project-automation Bot moved this from Untriaged to In Progress in Azure MCP Server Apr 29, 2026
@xiangyan99
Copy link
Copy Markdown
Member

Why use environment variables instead of explicit startup options?

I feel like environment variables can get messed with without users even noticing. What do you think?

@tloula
Copy link
Copy Markdown
Author

tloula commented Apr 30, 2026

@xiangyan99 this was my reasoning:

  • The codebase already uses AZURE_MCP_DANGEROUSLY_* env vars for similar opt-in security toggles (e.g., AZURE_MCP_DANGEROUSLY_DISABLE_*), so this slots in next to them. Keeping it consistent felt more valuable than introducing a parallel CLI-flag pattern just for this one knob.
  • MCP servers are launched from a JSON config block where both args and env are first-class, so from a "user has to consciously edit their config to set this" standpoint they're equivalent.
  • It's a deployment-time setting, not a per-call argument. Env vars feel like the natural fit for that vs. polluting the startup arg surface.
@xiangyan99
Copy link
Copy Markdown
Member

@xiangyan99 this was my reasoning:

  • The codebase already uses AZURE_MCP_DANGEROUSLY_* env vars for similar opt-in security toggles (e.g., AZURE_MCP_DANGEROUSLY_DISABLE_*), so this slots in next to them. Keeping it consistent felt more valuable than introducing a parallel CLI-flag pattern just for this one knob.
  • MCP servers are launched from a JSON config block where both args and env are first-class, so from a "user has to consciously edit their config to set this" standpoint they're equivalent.
  • It's a deployment-time setting, not a per-call argument. Env vars feel like the natural fit for that vs. polluting the startup arg surface.

'AZURE_MCP_DANGEROUSLY_DISABLE_' is only used in HTTP mode. If I understand correctly, the new env var you are introducing works for both HTTP and stdio (local MCP server)?

@tloula
Copy link
Copy Markdown
Author

tloula commented Apr 30, 2026

'AZURE_MCP_DANGEROUSLY_DISABLE_' is only used in HTTP mode. If I understand correctly, the new env var you are introducing works for both HTTP and stdio (local MCP server)?

Ah then yeah, the precedent doesn't quite apply here. I could switch to a CLI flag, but since KustoClient reads this at tool-invocation time (not server startup), it'd need plumbing through a config service vs. the self-contained env var lookup. Happy to do it if you think the ergonomics are worth the extra surface area though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment