Describe the bug
On Windows, the first Microsoft Entra account broker (WAM) sign-in for a remote MCP server on the built-in Entra fast-path list (here https://sentinel.microsoft.com/mcp/data-exploration) hard-crashes the CLI process with an access violation inside msalruntime.dll.
- Standalone CLI:
copilot exits immediately at startup. The terminal is left with mouse tracking enabled, so mouse movement prints escape sequences.
- GitHub Copilot Desktop: the pooled CLI process dies. The UI shows
Could not check authorization / WsCommandError: The pipe is being closed. (os error 232), and the MCP server dialog shows Connection failed: request cancelled. No browser or account picker ever appears.
It reproduces 100% of the time while the server is enabled (30+ crashes in one morning). Disabling the server stops the crashes.
Affected version
- 1.0.91 (npm), 1.0.93-1 (Copilot Desktop bundled CLI), 1.0.94-4 (npm). All crash identically.
- Windows 11, build 26200, x64. Device is hybrid Entra joined,
AzureAdPrt: YES, WamDefaultSet: YES, one WAM user account, zero WAM application accounts (dsregcmd /listaccounts).
Steps to reproduce the behavior
- Add an HTTP MCP server whose PRM points at Entra, e.g.
"Microsoft Sentinel Data Exploration": { "type": "http", "url": "https://sentinel.microsoft.com/mcp/data-exploration", "tools": ["*"] }
(PRM: authorization_servers: ["https://login.microsoftonline.com/organizations/v2.0"], scopes_supported: ["4500ebfb-89b6-4b14-a480-7f749797bfcd/.default"])
- Make sure there is no cached MCP token or retained broker account for it (fresh setup).
- Start
copilot, or open a session in Copilot Desktop.
- The log shows:
[ERROR] Connecting to Microsoft Sentinel Data Exploration...
[ERROR] Signing in with your Microsoft Entra account (account broker)...
About 0.5 s later the process terminates.
Expected behavior
The broker account picker is shown, parented to a valid window. If no usable parent window exists (no console, for example the Desktop app's pooled CLI), the CLI should fall back to browser or device-code OAuth or report an error. A sign-in failure must never take down the whole CLI process.
Additional context
Windows Application log (identical for every crash):
Faulting application name: copilot.exe, version: 1.0.94.0
Faulting module name: msalruntime.dll, version: 0.0.0.0, time stamp: 0x69f07b0a
Exception code: 0xc0000005
Fault offset: 0x0000000000143b98
Minidump analysis (two dumps: npm 1.0.94-4 in a terminal, and Desktop-pooled 1.0.93-1). Both are byte-for-byte the same failure:
- Access violation reading address 0x0 at
msalruntime.dll+0x143b98 (msalruntime PDB id 67FE1682B5B1454B934A6C477B9DF1A01).
- Faulting instructions:
mov rcx,[r13] → mov rax,[rcx] (rcx = 0) → mov rax,[rax+0x38] → call [__guard_dispatch_icall_fptr]. This is a virtual call on vtable slot 7 of a null WinRT interface pointer, and it matches C++/WinRT IAsyncInfo::get_Status, i.e. async.Status() / wait_for on a null async operation.
- The stack contains
Windows.Security.Authentication.Web.Core.dll frames. RTTI strings in the dump include AccountsSettingsPane / ShowAccountsControl, WebAccountProviderCommandInvokedHandler, and WebAccountProvider ... HWND helpers, so this is the interactive account-picker path.
Microsoft-Windows-AAD/Operational has no events at the crash times, so the request never reached the AAD broker plugin.
Likely root cause (from the bundled cli-main.js / msal-node-runtime.node):
- In
[entra-broker] sign-in, silent acquisition only runs when an account is already known. On first sign-in, broker discovery for the client returns no single account, so the code calls
acquireTokenInteractive({ scopes, prompt: SELECT_ACCOUNT, correlationId, openBrowser }) without a windowHandle.
NativeBrokerPlugin.acquireTokenInteractive then uses Buffer.from([0]) as the window handle → SignInInteractivelyAsync(HWND 0, ...).
- For HWND 0,
msal-node-runtime.node substitutes GetAncestor(GetConsoleWindow(), GA_ROOTOWNER) and falls back to GetDesktopWindow(). In a process with no console (the Desktop pooled CLI), or under a ConPTY host that doesn't reparent its pseudo-console window, WAM gets an unusable parent. msalruntime doesn't check the failed WinRT call and dereferences the null async operation.
Suggested fixes:
- Pass a real parent HWND to the broker. Copilot Desktop should supply its window; the terminal CLI should use the terminal's root window. Otherwise don't attempt an interactive broker sign-in when no valid window is available, and fall back to browser or device code (currently:
Entra broker cannot serve this server; not falling back to the browser).
- Guard against native broker crashes so they don't kill the CLI, e.g. run the broker out-of-process.
- Possibly report the null-deref to the MSAL runtime team.
Notes / workarounds observed:
Describe the bug
On Windows, the first Microsoft Entra account broker (WAM) sign-in for a remote MCP server on the built-in Entra fast-path list (here
https://sentinel.microsoft.com/mcp/data-exploration) hard-crashes the CLI process with an access violation insidemsalruntime.dll.copilotexits immediately at startup. The terminal is left with mouse tracking enabled, so mouse movement prints escape sequences.Could not check authorization/WsCommandError: The pipe is being closed. (os error 232), and the MCP server dialog showsConnection failed: request cancelled. No browser or account picker ever appears.It reproduces 100% of the time while the server is enabled (30+ crashes in one morning). Disabling the server stops the crashes.
Affected version
AzureAdPrt: YES,WamDefaultSet: YES, one WAM user account, zero WAM application accounts (dsregcmd /listaccounts).Steps to reproduce the behavior
authorization_servers: ["https://login.microsoftonline.com/organizations/v2.0"],scopes_supported: ["4500ebfb-89b6-4b14-a480-7f749797bfcd/.default"])copilot, or open a session in Copilot Desktop.Expected behavior
The broker account picker is shown, parented to a valid window. If no usable parent window exists (no console, for example the Desktop app's pooled CLI), the CLI should fall back to browser or device-code OAuth or report an error. A sign-in failure must never take down the whole CLI process.
Additional context
Windows Application log (identical for every crash):
Minidump analysis (two dumps: npm 1.0.94-4 in a terminal, and Desktop-pooled 1.0.93-1). Both are byte-for-byte the same failure:
msalruntime.dll+0x143b98(msalruntime PDB id67FE1682B5B1454B934A6C477B9DF1A01).mov rcx,[r13]→mov rax,[rcx](rcx = 0) →mov rax,[rax+0x38]→call [__guard_dispatch_icall_fptr]. This is a virtual call on vtable slot 7 of a null WinRT interface pointer, and it matches C++/WinRTIAsyncInfo::get_Status, i.e.async.Status()/wait_foron a null async operation.Windows.Security.Authentication.Web.Core.dllframes. RTTI strings in the dump includeAccountsSettingsPane/ShowAccountsControl,WebAccountProviderCommandInvokedHandler, andWebAccountProvider ... HWNDhelpers, so this is the interactive account-picker path.Microsoft-Windows-AAD/Operationalhas no events at the crash times, so the request never reached the AAD broker plugin.Likely root cause (from the bundled
cli-main.js/msal-node-runtime.node):[entra-broker]sign-in, silent acquisition only runs when an account is already known. On first sign-in, broker discovery for the client returns no single account, so the code callsacquireTokenInteractive({ scopes, prompt: SELECT_ACCOUNT, correlationId, openBrowser })without awindowHandle.NativeBrokerPlugin.acquireTokenInteractivethen usesBuffer.from([0])as the window handle →SignInInteractivelyAsync(HWND 0, ...).msal-node-runtime.nodesubstitutesGetAncestor(GetConsoleWindow(), GA_ROOTOWNER)and falls back toGetDesktopWindow(). In a process with no console (the Desktop pooled CLI), or under a ConPTY host that doesn't reparent its pseudo-console window, WAM gets an unusable parent.msalruntimedoesn't check the failed WinRT call and dereferences the null async operation.Suggested fixes:
Entra broker cannot serve this server; not falling back to the browser).Notes / workarounds observed:
az account get-access-token --resource 4500ebfb-89b6-4b14-a480-7f749797bfcd) and calling the MCP endpoint directly works fine (initialize,tools/list,tools/callall succeed). So the account, consent, and network are fine; only the broker interactive path fails.