MSAL.NET NativeInterop Core.Dispose invalidates an unrelated GCHandle

Vince Hardwick 25 Reputation points
2026-10-19T12:51:17.18+00:00

Has anyone found a safe workaround for this MSAL.NET NativeInterop defect while it awaits triage?

Issue #6220 reports that after removing a Core.LogEvent handler, disposing Core invalidates an unrelated GCHandle allocated by the caller. The public issue includes a standalone reproduction and reports the behavior with Microsoft.Identity.Client.NativeInterop 0.20.6, also used by Microsoft.Identity.Client.Broker 4.91.0.

I have asked for triage on the original GitHub issue: https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/issues/6220 (no maintainer response yet as of 19 October 2026).

Is there a known safe workaround, or should users avoid this event subscribe/unsubscribe sequence until the issue is assessed? The report says leaving the handler subscribed avoids its minimal reproduction, but that has not been assessed as a general workaround for Broker applications?

Microsoft Security | Microsoft Entra | Microsoft Entra ID

1 answer

Sort by: Most helpful
  1. AI answer

    2026-10-19T12:52:07.2466667+00:00

    There is currently no confirmed safe workaround for #6220; avoid manually subscribing and unsubscribing Core.LogEvent, and use MSAL.NET’s public logging API instead of treating “leave the handler subscribed” as a production mitigation.

    What is established

    The report remains open and covers Microsoft.Identity.Client.NativeInterop 0.20.6 on .NET Framework 4.8, where the standalone reproduction uses Core directly without authentication, broker operation, or an identity provider.^1^

    Consequently:

    • The reproduction demonstrates corruption following the subscribe → unsubscribe → dispose sequence.
    • It does not establish that leaving the handler subscribed is safe across repeated Core lifetimes, concurrent callbacks, or Broker shutdown.
    • It also does not establish that every Broker application will encounter the defect. The minimal reproduction bypasses the Broker path.
    • No matching fix or pull request has been identified, and MSAL.NET 4.91.0 cannot be considered to contain a fix merely because it carries NativeInterop 0.20.6.

    The older callback-lifetime bug #3578 is not a workaround for this case. It involved a native callback reaching a garbage-collected managed delegate and was reported fixed in MSAL.NET 4.47.0; #6220 presents a different lifetime sequence and must be assessed independently.^2^

    Applications using Core directly

    1. Remove application-level use of Core.LogEvent where possible.
    2. Do not add an unsubscribe-before-dispose operation merely to clean up the handler.
    3. Do not deliberately keep the handler subscribed and then dispose Core as a claimed fix; that variation only avoids the current minimal reproduction.
    4. If direct Core logging is indispensable, keep the affected code out of production or isolate it in a disposable helper process until maintainers define a safe lifetime contract or release a fix. Process isolation prevents native-memory corruption from compromising the main application.
    5. Retain the standalone reproducer as a regression test and rerun it against any candidate NativeInterop update before deployment.

    Avoid attempting to “repair” the caller’s GCHandle afterward. Once interop code has freed or corrupted a handle incorrectly, allocating another handle or suppressing Free() does not restore a reliable process state.

    Applications using Microsoft.Identity.Client.Broker

    Do not reproduce the direct-Core workaround inside application code. Continue using the Broker through its public MSAL.NET APIs, and avoid reflection or direct access to its NativeInterop Core.

    For diagnostics, configure logging when constructing the MSAL application with WithLogging(IIdentityLogger, Boolean). This is the documented logging surface; PII logging is disabled unless explicitly enabled.^3^

    var logger = new MyIdentityLogger();
    
    var app = PublicClientApplicationBuilder
        .Create(clientId)
        .WithBroker(new BrokerOptions(BrokerOptions.OperatingSystems.Windows))
        .WithLogging(logger, enablePiiLogging: false)
        .Build();
    

    If a Broker application is actually crashing or detects handle invalidation, add that concrete Broker reproduction to #6220, including:

    • Exact MSAL.NET, Broker, and NativeInterop versions.
    • .NET runtime, architecture, and Windows build.
    • Whether disposal races with token acquisition or shutdown.
    • A minimal dump or stack showing the invalid GCHandle.
    • MSAL logs with sensitive information removed.

    MSAL recommends enabling logging for diagnosis, using Informational normally and enabling Verbose only temporarily; network traces can contain PII and credentials and must be sanitized before posting.^3^

    Practical decision

    Until #6220 receives maintainer triage or a fixed package:

    • Direct NativeInterop use: avoid the LogEvent subscribe/unsubscribe/dispose sequence.
    • Broker use without observed failure: do not alter Broker internals based solely on the direct-Core reproduction.
    • Broker use with a matching failure: isolate or disable the affected Broker path if operationally possible and provide a Broker-specific reproduction.
    • Leaving the handler subscribed: regard it only as a reproduction observation, not a generally safe workaround.

    References

    1. #6220 Bug NativeInterop Core.Dispose invalidates an unrelated GCHandle after LogEvent is unsubscribed
    2. #3578 Bug A callback was made on a garbage collected delegate of type 'Microsoft.Identity.Client.NativeInterop'
    3. Logging in MSAL.NET
    AI-generated content may be incorrect. Read our transparency notes for more information.

    Was this answer helpful?

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.