Open karlra opened 1 year ago
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.
Tagging subscribers to this area: @dotnet/area-microsoft-win32 See info in area-owners.md if you want to be subscribed.
Author: | karlra |
---|---|
Assignees: | - |
Labels: | `area-Microsoft.Win32`, `untriaged` |
Milestone: | - |
The above does not happen. Why is it trying to load a Win32 registry module on Linux?
Microsoft.Win32.Registry is part of the shared framework and is used when resolving any of these types: https://github.com/dotnet/runtime/blob/main/src/libraries/Microsoft.Win32.Registry/ref/Microsoft.Win32.Registry.cs. Do you use reflection or load assemblies dynamically, given that this happened randomly after a month?
Steps To Reproduce Unknown, happened randomly on a production system
Unfortunately we can't investigate this issue further without repro steps or a full stack trace.
This issue has been marked needs-author-action
and may be missing some important information.
No, we are not using reflection or loading any assemblies dynamically. This is a very simple MVC app, I can't imagine that this is driven by user code. The stack trace I provided refers to internal Microsoft code, no?
@javiercn can we please move that issue back into aspnetcore? From the stacktrace, https://github.com/dotnet/aspnetcore/blob/73690575fd21834bda000f542c0d686427f113ae/src/DataProtection/DataProtection/src/KeyManagement/KeyRingProvider.cs#L206 throws the FileNotFoundException
so something on that path must depend on Win32.Registry types.
Can I take a guess that the issue is here: https://github.com/dotnet/aspnetcore/blob/73690575fd21834bda000f542c0d686427f113ae/src/DataProtection/DataProtection/src/LoggingExtensions.cs#L182
on line 157-158, where it references RegistryKey and using Microsoft.Win32 in the header?
That makes sense yes. What I don't understand is why the FileNotFoundException happens given that Microsoft.Win32.Registry.dll
is part of the targeting pack, the shared framework and the runtime pack on all platforms. Even though it does throw PlatformNotSupportedExceptions on Unix, it's still included in the layout.
cc @dougbu @wtgodbe @JamesNK (as this is an aspnetcore issue)
as this is an aspnetcore issue
That's not clear to me because the OP describes the issue as intermittent and happening in an app that's been running smoothly for weeks before the problem is hit. It's as if the file is getting deleted randomly.
If the problem occurs around the same time as a Visual Studio or Windows Update on the affected machine(s), that might be the explanation. I don't have a better idea at this point.
I just checked on the production server (that experienced this issue) and the file is there, in the /refs folder. It has correct permissions. Very strange.
Had the same issue on linux with .net7, but after redeploy it went away and I can't reproduce it.
I have observed this issue as well on DotNet 7.
System.Security.Cryptography.CryptographicException: An error occurred while trying to encrypt the provided data. Refer to the inner exception for more information. For more information go to http://aka.ms/dataprotectionwarning
---> System.TypeInitializationException: The type initializer for 'Microsoft.Extensions.Logging.LoggingExtensions' threw an exception.
---> System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.Win32.Registry, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.
The symptom is:
Since this issue only appears to happen after time, my hunch is that some logging-related object in this application was disposed. The best guess I have is that there is some tiny difference between the initial creation of the logging related object and the attempted recreation of the logging related object, which causes the recreation to fail.
Will share more details if I discover anything from our traces.
Possibly related: https://github.com/Azure/azure-storage-net/issues/969
Stumbled into the same problem:
dotnet run --project xyz
This happened to us today. .NET 8 Blazor app on Ubuntu. Other services unaffected. Rebooting the VM was required to resolve the issue.
System.Security.Cryptography.CryptographicException: An error occurred while trying to encrypt the provided data. Refer to the inner exception for more information.
---> System.TypeInitializationException: The type initializer for 'Microsoft.Extensions.Logging.LoggingExtensions' threw an exception.
---> System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.Win32.Registry, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.
File name: 'Microsoft.Win32.Registry, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
--- End of inner exception stack trace ---
at Microsoft.Extensions.Logging.LoggingExtensions.ErrorOccurredWhileRefreshingKeyRing(ILogger logger, Exception exception)
at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider.GetCurrentKeyRingCore(DateTime utcNow, Boolean forceRefresh)
at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.Protect(Byte[] plaintext)
--- End of inner exception stack trace ---
at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.Protect(Byte[] plaintext)
at Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.WriteNonceCookie(String nonce)
at Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.HandleChallengeAsyncInternal(AuthenticationProperties properties)
at Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.HandleChallengeAsync(AuthenticationProperties properties)
at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.ChallengeAsync(AuthenticationProperties properties)
at Microsoft.AspNetCore.Authentication.AuthenticationService.ChallengeAsync(HttpContext context, String scheme, AuthenticationProperties properties)
at Microsoft.AspNetCore.Authorization.Policy.AuthorizationMiddlewareResultHandler.<>c__DisplayClass0_0.<<HandleAsync>g__Handle|0>d.MoveNext()
--- End of stack trace from previous location ---
at PureBlazor.BlazorFrameworkAuthorizationMiddlewareResultHandler.HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult) in G:\repos\pureblazor\cms\src\PureBlazor\BlazorFrameworkAuthorizationMiddlewareResultHandler.cs:line 24
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.<Invoke>g__Awaited|10_0(ExceptionHandlerMiddlewareImpl middleware, HttpContext context, Task task)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.HandleException(HttpContext context, ExceptionDispatchInfo edi)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.<Invoke>g__Awaited|10_0(ExceptionHandlerMiddlewareImpl middleware, HttpContext context, Task task)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
tl;dr - combination of lazy dll loading and some linux-specific magic is probably the culprit. Workaround at the end.
Happens to our app too. Still running on .NET 6.0 and restarting the app helps. Usually it takes few months of uptime before it manifests. My first attempt to make sense of the exception stack: cookie auth (or any other code that uses DataProtector) is using existing valid keyring. At some point it expires and auto refresh tries to renew it. And as part of renewal it tries to log something, so static initializer of Microsoft.Extensions.Logging.LoggingExtensions
runs - and fails with the above exception. The intended log message is lost, instead we get the message about bad or missing Microsoft.Win32.Registry.
But if Win32.Registry was just broken and never load on linux, that would require that nothing ever uses the LoggingExtensions. Not even generating new keyring - or the app would break on startup. And message about new keyring definitely IS in the log.
But... it's long running app, running on linux. Which allows file overwrite while they are in use by running app, without forcing restart. And .NET runtime upgrade is just one apt-get upgrade
away. SO, it MAY be looking for exact patch version that was valid when the app was started, but no longer exists due to system upgrade (even when the message says it's looking for X.0.0.0).
With this in mind, I did some experiments, command ls -l /proc/<pid>/fd | grep in32
.
First run after encountering the problem and restarting service:
lr-x------ 1 wwwdata nogroup 64 Apr 3 12:23 209 -> /usr/share/dotnet/shared/Microsoft.NETCore.App/6.0.28/Microsoft.Win32.Registry.dll
After another restart: (empty, dll is not loaded)
Testing instance of the same app that has been running for a long time without user interaction - no Win32.Registry, but...
lr-x------ 1 wwwdata nogroup 64 Apr 3 12:24 170 -> /usr/share/dotnet/shared/Microsoft.NETCore.App/6.0.20/Microsoft.Win32.Primitives.dll (deleted)
(note the .20 version instead of .28, and (deleted) at the end).
My conclusion (and repro... kind of):
So, workaround should be something like this in Program.cs:
public static async Task Main(string[] args)
{
{
// https://github.com/dotnet/runtime/issues/81020
_ = typeof(Microsoft.Win32.Registry).Assembly;
}
...
}
I'd rather load Microsoft.Extensions.Logging.LoggingExtensions, but it's internal class. I've added it to our app as a test, but only thing I can report now is that it doesn't fail at startup and the win32 .dll is always loaded in memory. Reporting back if it helped will probably take a long time.
I'm getting the same issue with a .NET 8 RazorPages app on Ubuntu 22. Interestingly it happened in two different ways on two different servers in the cluster. In both cases, rebooting the servers resolved the issue.
The second one involves a different binary (Microsoft.AspNetCore.Diagnostics.Abstractions) but every other symptom was the same, i.e. the server was running fine for months before the issue happened, then the logs were flooded with 2Gb per day of errors.
The stack traces are below:
fail: Microsoft.AspNetCore.Server.Kestrel[13]
Connection id "0HN2FQ2B985GH", Request id "0HN2FQ2B985GH:00000001": An unhandled exception was thrown by the application.
System.InvalidOperationException: The exception handler configured on ExceptionHandlerOptions produced a 404 status response. This InvalidOperationException containing the original exception was thrown since this is often due to a misconfigured ExceptionHandlingPath. If the exception handler is expected to return 404 status responses then set AllowStatusCode404Response to true.
---> System.Security.Cryptography.CryptographicException: An error occurred while trying to encrypt the provided data. Refer to the inner exception for more information.
---> System.TypeInitializationException: The type initializer for 'Microsoft.Extensions.Logging.LoggingExtensions' threw an exception.
---> System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.Win32.Registry, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.
File name: 'Microsoft.Win32.Registry, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
--- End of inner exception stack trace ---
at Microsoft.Extensions.Logging.LoggingExtensions.ErrorOccurredWhileRefreshingKeyRing(ILogger logger, Exception exception)
at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider.GetCurrentKeyRingCore(DateTime utcNow, Boolean forceRefresh)
at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.Protect(Byte[] plaintext)
--- End of inner exception stack trace ---
at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.Protect(Byte[] plaintext)
at Microsoft.AspNetCore.Antiforgery.DefaultAntiforgeryTokenSerializer.Serialize(AntiforgeryToken token)
at Microsoft.AspNetCore.Antiforgery.DefaultAntiforgery.Serialize(IAntiforgeryFeature antiforgeryFeature)
at Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.GenerateForm(String actionName, String controllerName, Object routeValues, FormMethod method, Nullable`1 antiforgery, Object htmlAttributes)
at UGIPCore.Pages.Pages_SecurityLogin.ExecuteAsync()
at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageCoreAsync(IRazorPage page, ViewContext context)
at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageAsync(IRazorPage page, ViewContext context, Boolean invokeViewStarts)
at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderAsync(ViewContext context)
at Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, String contentType, Nullable`1 statusCode)
at Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, String contentType, Nullable`1 statusCode)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|30_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.<Invoke>g__Awaited|10_0(ExceptionHandlerMiddlewareImpl middleware, HttpContext context, Task task)
--- End of inner exception stack trace ---
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.HandleException(HttpContext context, ExceptionDispatchInfo edi)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.<Invoke>g__Awaited|10_0(ExceptionHandlerMiddlewareImpl middleware, HttpContext context, Task task)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
fail: Microsoft.AspNetCore.Server.Kestrel[13]
Connection id "0HN2FQ2DUKVBS", Request id "0HN2FQ2DUKVBS:00000001": An unhandled exception was thrown by the application.
System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.AspNetCore.Diagnostics.Abstractions, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. The system cannot find the file specified.
File name: 'Microsoft.AspNetCore.Diagnostics.Abstractions, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.HandleException(HttpContext context, ExceptionDispatchInfo edi)
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.HandleException(HttpContext context, ExceptionDispatchInfo edi)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.<Invoke>g__Awaited|10_0(ExceptionHandlerMiddlewareImpl middleware, HttpContext context, Task task)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
@huancz - it's been 4 months since you proposed your workaround. Can you please report the results?
@huancz - it's been 4 months since you proposed your workaround. Can you please report the results?
I've had his workaround on my servers since June, under similar conditions, and haven't seen the issue again. So it's not a guarantee of a fix but seems to have helped..
I have the same random crash (after long running) on Ubuntu with a web api in .net 8.
Could not load file or assembly 'System.Web.HttpUtility, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. The system cannot find the file specified.\n\n
Is there any fix planed because actually this is ruining my app stability on time ?
The workaround is really painful as I have to figure out all the dll referenced and call it on main func... On big application it's really boring.
@Safirion
The issue seem to be architectural, and impossible to be "fixed". Proper "fix" is to make sure you restart your apps when you update dotnet runtime on your server. Or don't update the runtime when you can't afford to restart apps.
We have since moved most of our apps to podman containers where it can't happen (not because of this issue, it's just better for security, and there is no support for older runtimes on newest ubuntu).
edit: I guess they could implement some opt-in eager dll loading. Which, honestly, seems like an overkill to fix something that's essentially user error - broken server management policy. Maybe if broader use case could be found... I wouldn't hold my breath.
An option to disable this lazy loading of dll or just use the later one instead of the one present at the moment of the application starts certainly fix this issue.
It's not a broken management policy to run daily update task and I don't think that it was to the developer to takes in charge the bad management of dll loading on Linux (windows .net runtime update don't crash .net apps currently running on it)
It's a bad policy, because you may think your apps are secure and up to date, but they are still using the old vulnerable dlls. Allowing them to use mixed dlls from multiple runtimes seems like recipe for huge trouble too.
Windows dotnet update requires you to restart windows if any app is using those dlls. Linux is much more forgiving.
It's not ideal, I agree, but it's far better than a crash in production in both cases.
Edit : I will use this method in main to ensure all assemblies are loaded at application startup. It will delay my application start by few seconds but at least it should not crash after start. 🤞
public static void LoadAllAssemblies()
{
Assembly rootAssembly = Assembly.GetEntryAssembly();
HashSet<string> visited = new();
Queue<Assembly> queue = new();
queue.Enqueue(rootAssembly);
while (queue.Any())
{
Assembly assembly = queue.Dequeue();
visited.Add(assembly.FullName);
AssemblyName[] references = assembly.GetReferencedAssemblies();
foreach (AssemblyName reference in references)
{
if (!visited.Contains(reference.FullName))
queue.Enqueue(Assembly.Load(reference));
}
}
}
@huancz Thanks for the idea 👍
Is there an existing issue for this?
Describe the bug
At a random point, where according to the logs it appears nobody was using our web app, the app stopped accepting requests entirely. The app had an uptime of over a month at the point where this happened and nothing like this has happened before on any of our apps, which all have very long uptimes and most of them have tens or hundreds of thousands of users.
The following was spammed to the error logs, again and again (over 1000 such log entries over ~4 minutes until we manually restarted). It cannot be request driven because this is a low traffic app and does not have so many visitors in a 4 minute interval.
Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[1] An unhandled exception has occurred while executing the request. System.Security.Cryptography.CryptographicException: An error occurred while trying to encrypt the provided data. Refer to the inner exception for more information. For more information go to http://aka.ms/dataprotectionwarning ---> System.TypeInitializationException: The type initializer for 'Microsoft.Extensions.Logging.LoggingExtensions' threw an exception. ---> System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.Win32.Registry, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.
File name: 'Microsoft.Win32.Registry, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' --- End of inner exception stack trace --- at Microsoft.Extensions.Logging.LoggingExtensions.ErrorOccurredWhileRefreshingKeyRing(ILogger logger, Exception exception) at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider.GetCurrentKeyRingCore(DateTime utcNow, Boolean forceRefresh) at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.Protect(Byte[] plaintext) --- End of inner exception stack trace --- at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.Protect(Byte[] plaintext) at Microsoft.AspNetCore.Session.CookieProtection.Protect(IDataProtector protector, String data) at Microsoft.AspNetCore.Session.SessionMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
Expected Behavior
The above does not happen. Why is it trying to load a Win32 registry module on Linux?
Steps To Reproduce
Unknown, happened randomly on a production system
Exceptions (if any)
Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[1] An unhandled exception has occurred while executing the request. System.Security.Cryptography.CryptographicException: An error occurred while trying to encrypt the provided data. Refer to the inner exception for more information. For more information go to http://aka.ms/dataprotectionwarning ---> System.TypeInitializationException: The type initializer for 'Microsoft.Extensions.Logging.LoggingExtensions' threw an exception. ---> System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.Win32.Registry, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.
File name: 'Microsoft.Win32.Registry, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' --- End of inner exception stack trace --- at Microsoft.Extensions.Logging.LoggingExtensions.ErrorOccurredWhileRefreshingKeyRing(ILogger logger, Exception exception) at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider.GetCurrentKeyRingCore(DateTime utcNow, Boolean forceRefresh) at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.Protect(Byte[] plaintext) --- End of inner exception stack trace --- at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.Protect(Byte[] plaintext) at Microsoft.AspNetCore.Session.CookieProtection.Protect(IDataProtector protector, String data) at Microsoft.AspNetCore.Session.SessionMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
.NET Version
6.0.13
Anything else?
Running on Ubuntu 18.04.
global.json file: Not found
Host: Version: 6.0.13 Architecture: x64 Commit: 1af80ba017
.NET SDKs installed: No SDKs were found.
.NET runtimes installed: Microsoft.AspNetCore.App 6.0.13 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App] Microsoft.NETCore.App 6.0.13 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
Download .NET: https://aka.ms/dotnet-download
Learn about .NET Runtimes and SDKs: https://aka.ms/dotnet/runtimes-sdk-info