Skip to content

Windows: CLI crashes (0xc0000005 in msalruntime.dll) on first Entra account-broker sign-in for MCP server - interactive WAM called with no parent window #5088

Description

@dcallahanmth

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

  1. 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"])
  2. Make sure there is no cached MCP token or retained broker account for it (fresh setup).
  3. Start copilot, or open a session in Copilot Desktop.
  4. 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):

  1. 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.
  2. NativeBrokerPlugin.acquireTokenInteractive then uses Buffer.from([0]) as the window handle → SignInInteractivelyAsync(HWND 0, ...).
  3. 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:

Activity

  1. added
    area:authenticationLogin, OAuth, device auth, token management, and keychain integration
    area:mcpMCP server configuration, discovery, connectivity, OAuth, policy, and registry
    area:platform-windowsWindows-specific: PowerShell, cmd, Git Bash, WSL, Windows Terminal
    and removed on Oct 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:authenticationLogin, OAuth, device auth, token management, and keychain integrationarea:mcpMCP server configuration, discovery, connectivity, OAuth, policy, and registryarea:platform-windowsWindows-specific: PowerShell, cmd, Git Bash, WSL, Windows Terminal

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions