If you are moving devices to Windows 11 24H2, there is a critical security problem you should know about. On Windows 11 24H2, Constrained Language Mode is no longer enforced correctly when using AppLocker Script Rules.
PowerShell scripts that should run under restricted conditions now run fully unrestricted in Full Language Mode. This creates a real security gap that administrators need to address before upgrading. This blog explains what changed between 23H2 and 24H2 and what you need to be aware of!
Why Application Restrictions Matter
Application control is a critical part of securing Windows environments. Blocking unauthorized code from running is one of the most effective ways to reduce attack surface, prevent lateral movement, and stop exploits that rely on executing new or modified binaries. AppLocker allows organizations to define exactly which executables, installers, and scripts are permitted. In addition to managing traditional applications, AppLocker can also apply control over scripts such as PowerShell scripts and batch files.
By enforcing Applocker script rules, administrators can ensure that only trusted, intended automation runs across devices, reducing the risk of abuse through scripting engines like PowerShell.
Full Language Mode vs Constrained Language Mode in PowerShell
When PowerShell scripts are allowed to run without restriction, PowerShell operates in Full Language Mode. In this mode, scripts have access to the full capabilities of the platform, including .NET libraries, direct API calls, and dynamic code execution.
Constrained Language Mode provides a much more limited environment. Scripts running under CLM are restricted to basic cmdlets and approved types. They cannot create new .NET objects, access external libraries, or perform advanced operations that could compromise a device. This mode is critical for ensuring that even if a script runs, privileges cannot be escalated easily.
Feature | Full Language Mode | Constrained Language Mode |
---|---|---|
Access to .NET APIs | Full access | Blocked |
Create custom types | Allowed | Blocked |
P/Invoke and native calls | Allowed | Blocked |
Reflection and dynamic code | Allowed | Blocked |
Use basic cmdlets | Allowed | Allowed |
For a deeper technical explanation of how Constrained Language Mode works, refer to the Patch My PC blog here.
How PowerShell Determines Language Mode Based on AppLocker Script Rules
When PowerShell starts, it checks whether AppLocker Script Enforcement Rules are present. It does this by simulating the execution of a test PowerShell script placed in the user’s temporary folder and evaluating it against the system’s policies. As shown below, the DLL (System.Management.Automation.dll) responsible for PowerShell shows this behavior.
This means that if AppLocker’s rules block or restrict the test PS1 file, PowerShell automatically switches into Constrained Language Mode.
If no restrictions apply, PowerShell Scripts will be executed in full language mode. This automatic detection has worked reliably for years and has been a simple way to enforce script safety without needing extra configuration inside PowerShell itself.
Constrained Language Mode Windows 11 24H2
With Windows 11 24H2, this behavior has quietly changed. Even with AppLocker Script Rules correctly configured and enforced, PowerShell scripts are no longer executed in contained language mode but in Full language mode, which is pretty bad!
To find out what changed, we performed some tests. We first executed this PowerShell command from a user session with Applocker script enforcement active.
$ExecutionContext.SessionState.LanguageMode
[System.Console]::WriteLine("Hello")
As shown below, it first indeed showed us that constrainedlanguage was active and it blocked the WriteLine command, mentioning that the method invocation is not supported.
But!!! As shown above, executing a PowerShell script with the same PowerShell command from that same user session showed us that it was running FullLanguage. With the PowerShell script running in full language mode, it indeed also showed the Hello output! That’s not good data at all and not expected behavior!
During the second test, the same default AppLocker policies behaved correctly on Windows 11 23H2, making it clear that the change was specific to the new Windows 11 24h2 version.
As shown above, AppLocker’s contained language mode enforcement still worked; executing scripts were executed in constrained language mode.
At first, I had the idea that Microsoft changed something in the Applocker code, but given that Microsoft is not putting any effort into updating Applocker anymore (it is deprecated), it was clear that we needed to start looking at how PowerShell was dealing with Applocker.
System.Management.Automation.dll in Windows 11 24h2
To find the root cause, we decided to do something stupid. We started the test by replacing the newer System.Management.Automation.dll from Windows 11 24H2 with the older version from a Windows 11 23H2 build. We did so by using the Recovery Environment, as the file was always in use by Windows itself.
After we replaced the system.management.automation.dll with an older version, we re-ran the same test. This time, after running the PowerShell script, PowerShell immediately returned to its expected behavior: enforcing Constrained Language Mode when AppLocker Script Rules were active.
This confirmed that the replaced DLL was responsible for breaking the enforcement of constrained language mode.
Windows 11 24H2: CanExecuteFile
After discovering that the DLL update caused the behavioral change, a deeper investigation into the system’s evaluation flow revealed a second important change. Windows 11 24H2 introduced a new step: before checking lockdown policies, the system now first calls a new method named WldpCanExecuteFile.
If WldpCanExecuteFile allows the script to execute, PowerShell immediately runs in Full Language Mode without consulting the lockdown policy. Only if execution is blocked by CanExecuteFile does the system fall back to evaluating the lockdown policy.
Somehow, it feels like that with the additional Wldp functionality being added, Microsoft could have potentially broken the Applocker constrained language mode.
Please Note: This is pure speculation…
Why Manual DLL Replacement Is Not a Real Solution
Even though replacing the DLL temporarily restores expected behavior, Windows File Protection mechanisms and servicing updates will eventually overwrite unauthorized changes. Tampering with protected system components risks system instability and breaks the official Windows update path. A real solution must work within the supported platform model.
Moving to Windows Defender Application Control (WDAC)
The sustainable way forward is to move from relying on AppLocker alone to using Windows Defender Application Control (WDAC). WDAC operates deeper in the Windows security model and can enforce Constrained Language Mode through trusted code integrity policies. WDAC guarantees that scripts run in restricted environments, even if underlying system behaviors like CanExecuteFile checks are introduced. Although implementing WDAC requires careful planning and testing, it provides stronger guarantees than AppLocker alone, especially on evolving platforms like Windows 11 24H2.
Conclusion:
Windows 11 24H2 introduces a serious but subtle change that affects environments relying on AppLocker Script Rules to control PowerShell. Organizations upgrading to 24H2 must review and update their security strategies. AppLocker Script Rules alone will no longer guarantee script restriction.