Hi all,
we are currently testing Windows Defender Application Control (= WDAC) to lock down a hardened host pool. One core feature of WDAC is script enforcement. In a nutshell, it forces unsigned scripts and interactive powershell sessions into constrained language, while scripts signed with a trusted certificate are allowed to run in full language.
Important note: Full language code must not be executed in a constrained language environment and vice versa, eg.
- Trying to run a signed script by dot sourcing it from an interactive session
- Calling an unsigned script within a signed script
Crossing the boundary between languages is explicitly forbidden by design. This is what I believe is causing scripts executed via Nerdios' scripted actions to fail:
C:\\Packages\\Plugins\\Microsoft.Compute.CustomScriptExtension\\1.9.5\\Downloads\\0\\be7c94b1-6a24-403c-9637-a1f9fc05aabf.ps1:
Cannot dot-source this command because it was defined in a different language mode. To invoke this command without
importing its contents, omit the \u0027.\u0027 operator.
CategoryInfo : InvalidOperation: (:) [be7c94b1-6a24-403c-9637-a1f9fc05aabf.ps1], NotSupportedException
FullyQualifiedErrorId : DotSourceNotSupported,be7c94b1-6a24-403c-9637-a1f9fc05aabf.ps1
To get a better understanding of what's happening, I've enabled powershell transcription on our test host:
**********************
Windows PowerShell transcript start
Start time: 20260202145847
Username: WORKGROUP\SYSTEM
RunAs User: WORKGROUP\SYSTEM
Configuration Name:
Machine: AZVMTST001 (Microsoft Windows NT 10.0.26200.0)
Host Application: powershell -ExecutionPolicy Unrestricted -File be7c94b1-6a24-403c-9637-a1f9fc05aabf.ps1 -ScriptName ef59550daacb9c7c1698e712d7b449a9.ps1 -ScriptParameters <redacted>
Process ID: 1536
PSVersion: 5.1.26100.7462
PSEdition: Desktop
PSCompatibleVersions: 1.0, 2.0, 3.0, 4.0, 5.0, 5.1.26100.7462
BuildVersion: 10.0.26100.7462
CLRVersion: 4.0.30319.42000
WSManStackVersion: 3.0
PSRemotingProtocolVersion: 2.3
SerializationVersion: 1.1.0.1
**********************
**********************
Command start time: 20260202145848
**********************
PS>C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension\1.9.5\Downloads\0\be7c94b1-6a24-403c-9637-a1f9fc05aabf.ps1
Cannot dot-source this command because it was defined in a different language mode. To invoke this command without importing its contents, omit the '.' operator.
C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension\1.9.5\Downloads\0\be7c94b1-6a24-403c-9637-a1f9fc05aabf.ps1
: Cannot dot-source this command because it was defined in a different language mode. To invoke this command without
importing its contents, omit the '.' operator.
+ CategoryInfo : InvalidOperation: (:) [be7c94b1-6a24-403c-9637-a1f9fc05aabf.ps1], NotSupportedException
+ FullyQualifiedErrorId : DotSourceNotSupported,be7c94b1-6a24-403c-9637-a1f9fc05aabf.ps1
**********************
Windows PowerShell transcript end
End time: 20260202145848
**********************
Both files be7c94b1-6a24-403c-9637-a1f9fc05aabf.ps1 and ef59550daacb9c7c1698e712d7b449a9.ps1 are signed with a trusted signing certificate and run fine by themselves. The problem seems to stem from running powershell with the -File parameter, as described here:
Scenario 2: The Hidden Trigger - PowerShell.exe -File with [CmdletBinding()]
This is the less obvious scenario that catches many people off guard. When you use both of these conditions together:
- PowerShell.exe -File script.ps1 (using the -File parameter)
- The script contains [CmdletBinding()]
PowerShell automatically uses dot sourcing behavior, which can trigger the language mode boundary crossing issue. Neither condition alone causes problems - it's specifically their combination.
I am able to reproduce the described behaviour:
- Running powershell -ExecutionPolicy Unrestricted -File be7c94b1-6a24-403c-9637-a1f9fc05aabf.ps1 -ScriptName ef59550daacb9c7c1698e712d7b449a9.ps1 -ScriptParameters <redacted> causes the dot sourcing error
- Running powershell -ExecutionPolicy Unrestricted -Command ".\be7c94b1-6a24-403c-9637-a1f9fc05aabf.ps1 -ScriptName ef59550daacb9c7c1698e712d7b449a9.ps1 -ScriptParameters <redacted>" works as expected
Solution:
Change the Azure Custom Script Extension execution triggered by nerdio to not use dot sourcing by calling powershell with the -Command parameter instead of -File
If you need any more information to reproduce this behaviour in your lab, feel free to ask.
Comments (2 comments)