Release Date:February 25, 2025

Version:.NET 8 and higher.NET Framework, all versions

Summary

Microsoft has rolled out security improvements to recent versions of Windows. These security improvements modify temp path handling and may cause certain .NET Framework and .NET APIs like ​​​​​​​​​​​​​​System.IO.Path.GetTempPath()to return a different location after the patch is applied.​​​​​​​

Action required

No action is required of any .NET Framework or .NET-based application. Your application will automatically benefit from any security improvements applicable to your environment. Most applications will not observe any behavioral change. 

The remainder of this article details how to determine if these security improvements may impact the runtime behavior of your application. This article also lists steps for customizing the runtime behavior if desired

Applicable Software

This article applies to the following software: 

Only when running on the following Windows update versions: 

  • Windows 10, version 22H2 when KB5052077 is installed

  • Windows Server 2019, when KB5053594 is installed 

  • Windows Server 2016, when KB5053594 is installed 

This article does not apply to .NET Framework or .NET running on Windows 11, Windows Server 2022, or later. 

This article does not apply to .NET when running on non-Windows platforms. 

Detailed description and impact statement

As of the Windows update KBs mentioned above, Microsoft has backported the Win32 GetTempPath2 API to older in-market versions of Windows to act as a more secure replacement for the older Win32 GetTempPath API. Internally, .NET Framework and .NET rely on these Win32 APIs to provide the implementation of the System.IO.Path.GetTempPath() method: the Win32 GetTempPath2 API is preferred if it exists; and the Win32 GetTempPath API is used as a fallback if GetTempPath2 does not exist. 

Because these KBs make the new Win32 GetTempPath2 API available on the applicable platforms, .NET Framework and .NET will begin using GetTempPath2 once the KBs have been installed. 

The primary behavioral change is that callers who are running as the SYSTEM identity will observe the System.IO.Path.GetTempPath() method return %WINDIR%\SystemTemp by default, whereas callers who are running as anything other than the SYSTEM identity will observe the method continue to return its existing value. 

If your application meets all the below criteria, you may be impacted by this change: 

  • Your application utilizes a runtime and OS platform listed under the earlier "Applicable Software" heading; and

  • Your application runs as the SYSTEM identity; and

  • You manually set the %TMP% or %TEMP% environment variable to redirect the standard temp file location. (See the Remarks section of the Win32 GetTempPath API documentation.)

If you meet all these criteria, then once the Windows KBs are installed, you may observe your application writing to a temp directory other than the directory you intended. 

This behavioral change may be visible through any .NET Framework or .NET-provided API which eventually relies on GetTempPath2. The most common entry points are: 

This is not intended to be an exhaustive list of methods whose behaviors might change once the KBs are installed. 

Determining whether an application runs under the SYSTEM identity 

There are several different mechanisms for determining the identity of a .NET Framework or .NET application

IIS-based web applications 

IIS refers to the SYSTEM identity as "LOCALSYSTEM". In the IIS Manager (inetmgr.exe), go to the Application Pools tab to see all app pools and their associated identities. You can also select "Identity" from the Group by dropdown to make it easier to see app pools which are running as the LOCALSYSTEM identity. 

The screenshot below shows an example of an app pool ("MyAppPool") which is configured to run as LOCALSYSTEM. Any applications running within this app pool will run as the SYSTEM identity. 

The screenshot shows an example of an app pool ("MyAppPool") which is configured to run as LOCALSYSTEM. Any applications running within this app pool will run as the SYSTEM identity.

You can also access this information programmatically from an elevated PowerShell session by using the script below. 

Import-Module IISAdministration  Get-IISAppPool | where {$_.ProcessModel.IdentityType -eq "LocalSystem"} 

In a machine configured with a SYSTEM-level "MyAppPool" app pool as shown in the screenshot above, this PowerShell script prints the following, showing that "MyAppPool" is running under the SYSTEM identity. 

Name                 Status       CLR Ver  Pipeline Mode  Start Mode  ----                 ------       -------  -------------  ---------- MyAppPool            Started      v4.0     Integrated     OnDemand 

Windows services 

If your .NET Framework or .NET-based application is registered as a Windows Service, you can use the Services manager to view its associated identity. 

From an elevated command prompt, run services.msc. This displays the Services manager UI. 

From an elevated command prompt, run services.msc. This displays the Services manager UI.

If the Log On As column lists "Local System" for the service identity, then the service is running under the SYSTEM identity. 

You can also query this data via PowerShell by using the Get-Service cmdlet. For example, to query this information for a service named MyService, use the following command. 

(Get-Service MyService).UserName -ieq "LocalSystem" 

If the service is registered to run under the SYSTEM identity, this will print True to the console. 

Other mechanisms 

Tools like Task Manager (taskmgr.exe) or Sysinternals Process Explorer can also tell you whether an application is running under the SYSTEM identity. 

In Task Manager, use the Details view to list all running processes in the system, then locate the process of interest and look at the entry under the User name column. 

In Task Manager, use the Details view to list all running processes in the system, then locate the process of interest and look at the entry under the User name column.

If the User name value reads "SYSTEM", the process is running under the SYSTEM identity. 

Or, in Sysinternals Process Explorer, locate the process of interest and enter the Properties view, then look at the User field under the Image tab. 

in Sysinternals Process Explorer, locate the process of interest and enter the Properties view, then look at the User field under the Image tab.

If the User value reads "NT AUTHORITY\SYSTEM", the process is running under the SYSTEM identity. 

Changing the temp path for SYSTEM-level processes 

The PowerShell script below demonstrates how to create a new directory C:\NewSystemTemp\ and restrict directory access to only processes running under the SYSTEM identity. Do not attempt to change the ACLs of a directory which is already populated with files. 

This script must be run from an elevated PowerShell session. 

mkdir C:\NewSystemTemp\  $acl = New-Object System.Security.AccessControl.DirectorySecurity  $acl.SetSecurityDescriptorSddlForm("O:SYG:SYD:PAI(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)")  Set-Acl C:\NewSystemTemp\ -AclObject $acl 

You can confirm that this operation was successful by running the command 

icacls C:\NewSystemTemp\ 

Which will produce the following output showing success: 

C:\NewSystemTemp\ NT AUTHORITY\SYSTEM:(OI)(CI)(F)                    BUILTIN\Administrators:(OI)(CI)(F)   Successfully processed 1 files; Failed processing 0 files 

Once the directory is created, set the %SYSTEMTEMP% environment variable with system-level scope. You can set this via the the System Control Panel UI, or you can set it programmatically via PowerShell: 

[Environment]::SetEnvironmentVariable("SYSTEMTEMP", "C:\NewSystemTemp", [EnvironmentVariableTarget]::Machine) 

Then reboot the machine. 

Changing the %SYSTEMTEMP% environment variable will not change the return value of System.IO.Path.GetTempPath() for .NET Framework and .NET applications which are running as an identity other than SYSTEM. Those applications will continue to follow the same resolution logic they always have, including honoring the %TMP% or %TEMP% environment variables if they are present. 

Similarly, setting the %TMP% or %TEMP% environment variable will not change the return value of System.IO.Path.GetTempPath() for .NET Framework and .NET applications which are running as the SYSTEM identity. 

For further information

For more information on .NET Framework and .NET behaviors, see the .NET documentation on Path.GetTempPath

For more information on the underlying Windows OS behavior, see the Windows documentation on the Win32 GetTempPath2 API.

Need more help?

Want more options?

Explore subscription benefits, browse training courses, learn how to secure your device, and more.