# Visual Studio Copilot and SSMS Remote Code Execution (CVE-2026-103572)

Trailing-dot filename bypass in Copilot's path validation let a prompt-injected agent write .mcp.json/settings and achieve RCE in Visual Studio and SSMS.

- Payout: Research
- Severity: high
- Program: Microsoft
- Write-up by: Johann Rehberger
- Disclosed: 2026-10-13
- CVE: CVE-2026-103572
- Write-up quality: 8/10
- Original: https://embracethered.com/blog/posts/2026/visual-studio-copilot-remote-code-execution/
- Library page: https://bugbountylibrary.com/r/blog%3Aembracethered-com-blog-posts-2026-visual-studio-copilot-remote-code-execution
- Tags: area:ai domain:ai domain:desktop impact:rce kind:research platform:research sev:high tech:llm technique:chained technique:source-review vuln:path-traversal vuln:prompt-injection vuln:rce

**Target:** Microsoft.VisualStudio.Copilot.Core.dll file-write validation in VS 2026 and SSMS
**Root cause:** EditsFunctionHandler.GetEditConfirmationTypeAsync compares raw filename strings against protected names, but Win32 canonicalization strips trailing dots, so '.mcp.json.' passes the check yet writes to '.mcp.json'.
**Steps:**
1. Prompt-inject the MAI-Code-1-Flash model with instructions to create/modify `settings.visualstudio.json.` (trailing dot) setting `copilot.general.tools.ripgrepPath` to `C:\Windows\System32\calc.exe`
2. Trigger a grep search so Copilot launches the configured ripgrepPath binary
3. Alternatively write `.mcp.json.` adding a malicious MCP server command, add its name to `enabledMcpServers`, remove from `disabledMcpServers`
4. Use path traversal from Extensions dir (`..\`) to read `SSMS.isolation.ini` and extract InstallationID
5. Write to `C:\Users\<user>\AppData\Local\Microsoft\SSMS\22.0_<InstallationID>\settings.json` to auto-enable the malicious MCP server
6. IDE launches MCP server, executing arbitrary command
**How found:** While validating fixes for SQL Copilot issues, noticed MCP support was newly added and investigated its implementation; spotted that the protected-filename check compared raw strings, then hypothesized Win32 trailing-dot canonicalization would defeat it.
**Exploitation:** Attacker delivers indirect prompt injection (e.g. via file content or MCP server data) to the Copilot agent; agent writes protected config files using trailing-dot names, injecting a malicious MCP server or ripgrepPath that the IDE then executes, yielding arbitrary command execution as the user.
**Escalation:** Chained path traversal to read SSMS.isolation.ini for InstallationID, enabling reliable settings.json targeting across installations; same primitive works in both VS and SSMS via shared DLL.
**Insight:** When an agent's file-write guard compares raw path strings, test Win32 canonicalization quirks: trailing dots/spaces, `..\` inside trusted prefixes, and `\\?\` extended paths, since the check and the actual write use different normalization.
