Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

[BUG] Process crashes with a stack overflow in Connect-PnPOnline after Teams or EXO Module connected (3.4.0 and later)

Chiusa
#5,480 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
52/100
Tipo di issue
Bug
Chiarezza
Abbastanza chiara
Stato di attività
Attiva
Stack tecnologico
csharp, powershell
Ambito
cli, devtools

Direzione di ricerca

Start with PnPAssemblyLoadContext and PnPPowerShellModuleInitializer.ResolveDependency, then run Repro-PnPStackOverflow.ps1 with an older Microsoft.Identity.Client loaded in the default context. Trace the repeated assembly-resolution path described in the issue. Done means the process survives Connect-PnPOnline and reaches the expected tenant-not-found error instead of crashing.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

bug
Reporting an Issue or Missing Feature

Issue. Since 3.4.0, the PowerShell process terminates when Connect-PnPOnline runs in a session in which another module has already loaded an older Microsoft.Identity.Client into the default AssemblyLoadContext. Connecting with MicrosoftTeams 8.0.0 (MSAL 4.82.0.0) or ExchangeOnlineManagement 3.9.2 (MSAL 4.74.1.0) causes it. PnP.PowerShell 3.4.x ships MSAL 4.85.2.0.

We found this in Microsoft365DSC, which connects to Microsoft Teams and other services from the same PowerShell 7 process.

Expected behavior

Connect-PnPOnline connects, as it does with 3.3.0.

Actual behavior

The process terminates, with no way to catch the error:

  • PowerShell 7.6 (.NET 10) prints Stack overflow. and exits with -1073741571 (0xC00000FD).
  • PowerShell 7.4 (.NET 8) usually exits with -1073741819 (0xC0000005) and doesn't print anything.
  • In a PowerShell remoting host (WinRM using the Local Configuration Manager LCM), the client reports The WSMan provider host process did not return a proper response.
Stack overflow.
Repeated 1207 times:
--------------------------------
   at System.Reflection.RuntimeAssembly.InternalLoad(System.Reflection.AssemblyName, System.Threading.StackCrawlMark ByRef, System.Runtime.Loader.AssemblyLoadContext, System.Reflection.RuntimeAssembly, Boolean)
   at System.Runtime.Loader.AssemblyLoadContext.LoadFromAssemblyName(System.Reflection.AssemblyName)
   at PnP.PowerShell.Commands.Base.PnPPowerShellModuleInitializer.ResolveDependency(System.Runtime.Loader.AssemblyLoadContext, System.Reflection.AssemblyName)
   at System.Runtime.Loader.AssemblyLoadContext.GetFirstResolvedAssemblyFromResolvingEvent(System.Reflection.AssemblyName)
   at System.Runtime.Loader.AssemblyLoadContext.ResolveUsingEvent(System.Reflection.AssemblyName)
--------------------------------
   at PnP.PowerShell.Commands.Base.PnPConnection.CreateWithCert(System.Uri, System.String, System.String, System.String, PnP.Framework.AzureEnvironment, System.Security.Cryptography.X509Certificates.X509Certificate2, Boolean)
   at PnP.PowerShell.Commands.Base.ConnectOnline.ConnectAppOnlyWithCertificate()
   at PnP.PowerShell.Commands.Base.ConnectOnline.Connect(System.Threading.CancellationToken ByRef)
   at PnP.PowerShell.Commands.Base.ConnectOnline.ProcessRecord()
Cause

#5393 (3.4.0) introduced PnPAssemblyLoadContext. For the boundary assemblies (Microsoft.Identity.Client* and System.Text.Json), Load returns null so that PnP reuses the host's copy whenever the default context holds an assembly with that simple name. It does not compare versions:

  1. PnP.PowerShell.dll (default context) references Microsoft.Identity.Client, Version=4.85.2.0. The default context holds 4.82.0.0, cannot bind the reference and raises Resolving.
  2. PnPPowerShellModuleInitializer.ResolveDependency finds Common\Microsoft.Identity.Client.dll and calls s_dependencyContext.LoadFromAssemblyName.
  3. PnPAssemblyLoadContext.Load sees a boundary assembly that the default context holds and returns null, so the runtime falls back to the default context.
  4. The default context still cannot bind 4.85.2.0 and raises Resolving again, which leads back to step 2. This repeats until the stack overflows.

Importing PnP.PowerShell first does not help if the other module loads its MSAL before the first Connect-PnPOnline. The same loop also happens when any caller requests a newer MSAL than the copy in the default context, even when PnP.PowerShell did not make the request.

Steps to reproduce behavior

In a fresh PowerShell 7 session:

Connect-MicrosoftTeams -ApplicationId $appId -CertificateThumbprint $thumbprint -TenantId 'contoso.onmicrosoft.com'
Connect-PnPOnline -Url 'https://contoso-admin.sharepoint.com' -ClientId $appId -Thumbprint $thumbprint -Tenant 'contoso.onmicrosoft.com'

Connect-ExchangeOnline instead of Connect-MicrosoftTeams crashes the same way.

I have a repro PowerShell script below that loads MSAL 4.82.0 from nuget.org into the default context, then runs Connect-PnPOnline with a throw-away certificate against a tenant that doesn't exist:

pwsh -NoProfile -File .\Repro-PnPStackOverflow.ps1; "exit code $LASTEXITCODE"
Repro-PnPStackOverflow.ps1
#Requires -Version 7.4
<#
.SYNOPSIS
    Reproduces the PnP.PowerShell 3.4.x process crash when the default AssemblyLoadContext already holds an older
    Microsoft.Identity.Client, as it does after Connect-MicrosoftTeams or Connect-ExchangeOnline.

.DESCRIPTION
    Loads Microsoft.Identity.Client 4.82.0 (downloaded from nuget.org, the version MicrosoftTeams 8.0.0 ships) into the
    default load context, imports PnP.PowerShell and runs Connect-PnPOnline. No tenant, credentials or other modules are needed.
    On an affected version it terminates the process.

.PARAMETER PnPModulePath
    Name or path of the PnP.PowerShell module to test.

.EXAMPLE
    pwsh -NoProfile -File .\Repro-PnPStackOverflow.ps1; "exit code $LASTEXITCODE"

    PnP.PowerShell 3.4.0 and 3.4.1 on PowerShell 7.6: prints 'Stack overflow.' and exits with -1073741571 (0xC00000FD).
    On PowerShell 7.4 it usually exits with -1073741819 (0xC0000005) without a message.
    In both cases the last line 'Process survived' is missing.
    PnP.PowerShell 3.3.0 or a fixed build: Connect-PnPOnline fails with AADSTS90002 (tenant not found), which is the
    expected result, and the script prints 'Process survived'.
#>
param(
    [Parameter()]
    [System.String]
    $PnPModulePath = 'PnP.PowerShell'
)

$ErrorActionPreference = 'Stop'

$msal = [System.Runtime.Loader.AssemblyLoadContext]::Default.Assemblies | Where-Object -FilterScript { $_.GetName().Name -eq 'Microsoft.Identity.Client' }
if ($null -eq $msal)
{
    $msalFolder = Join-Path -Path ([System.IO.Path]::GetTempPath()) -ChildPath 'msal-4.82.0'
    $msalPath = Join-Path -Path $msalFolder -ChildPath 'lib/net8.0/Microsoft.Identity.Client.dll'
    if (-not (Test-Path -Path $msalPath))
    {
        Invoke-WebRequest -Uri 'https://www.nuget.org/api/v2/package/Microsoft.Identity.Client/4.82.0' -OutFile "$msalFolder.zip"
        Expand-Archive -Path "$msalFolder.zip" -DestinationPath $msalFolder -Force
    }
    $msal = [System.Runtime.Loader.AssemblyLoadContext]::Default.LoadFromAssemblyPath($msalPath)
}
Write-Host "Default load context holds Microsoft.Identity.Client $($msal.GetName().Version)"

Import-Module -Name $PnPModulePath -DisableNameChecking
Write-Host "Imported PnP.PowerShell $((Get-Module -Name 'PnP.PowerShell').Version)"

$rsa = [System.Security.Cryptography.RSA]::Create(2048)
$request = [System.Security.Cryptography.X509Certificates.CertificateRequest]::new('CN=PnPRepro', $rsa, 'SHA256', [System.Security.Cryptography.RSASignaturePadding]::Pkcs1)
$certificate = $request.CreateSelfSigned([System.DateTimeOffset]::Now.AddDays(-1), [System.DateTimeOffset]::Now.AddDays(1))
try
{
    Connect-PnPOnline -Url 'https://pnprepro-invalid.sharepoint.com' -ClientId '11111111-1111-1111-1111-111111111111' -Tenant 'pnprepro-invalid.onmicrosoft.com' -CertificateBase64Encoded ([System.Convert]::ToBase64String($certificate.Export('Pfx')))
}
catch
{
    Write-Host "Connect-PnPOnline: $($_.Exception.GetType().FullName): $($_.Exception.Message)"
}

Write-Host 'Process survived'
PnP.PowerShell PowerShell 7.6.6 PowerShell 7.4.20
3.3.0 survives (AADSTS90002, expected) survives (AADSTS90002, expected)
3.4.1 crash, 0xC00000FD crash, 0xC0000005
dev at 6a978d96 crash, 0xC00000FD crash, 0xC0000005

Workaround until a fix ships: run Connect-PnPOnline before connecting to Microsoft Teams or Exchange Online in the same process, or stay on 3.3.0.

What is the version of the Cmdlet module you are running?

3.4.0 and 3.4.1. Also reproduced with a build of dev at 6a978d96.

Which operating system/environment are you running PnP PowerShell on?
  • Windows
  • Linux
  • MacOS
  • Azure Cloud Shell
  • Azure Functions
  • Other : PowerShell 7 remoting host (Windows PowerShell DSC relays class-based resources to a local PowerShell 7 session)

Windows 11 10.0.26300, PowerShell 7.6.6 and 7.4.20. Not tried on Linux or macOS, but they're most likely affected as well.

Lingua principale
C#
Stelle
906
Fork
408
Merge medio
2g 2h
PR unite (30g)
11

Preparare l'ambiente

Apri in Codespaces

Avvia il container di sviluppo del progetto nel browser, con il tuo account GitHub.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di pnp/powershell

Tutte le issue di pnp/powershell

Issue simili

Altre issue su C#

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.