You have a task that requires a PowerShell script, and you downloaded one from the internet. But when you run it, you get the following error message:
One of the key safety features in PowerShell is the Execution Policy, which determines the level of trust for executing scripts. In this blog post, we will explore the different aspects of managing script execution policy using the PowerShell Set-ExecutionPolicy cmdlet.
Table of Contents
Understanding PowerShell Script Execution Policy Type and Scope
PowerShell Execution Policy is a safety feature that controls the conditions under which PowerShell scripts can run. It helps prevent the execution of malicious scripts and provides control over the scripts that can be executed on a system.
The execution policy can be set at different scopes, allowing administrators to define the policy for specific users, processes, or machines.
Execution Policy Types
PowerShell provides several execution policy types, each with different levels of security and restrictions. The available execution policy types are:
- AllSigned: Requires that all scripts and configuration files be signed by a trusted publisher before they can be executed.
- RemoteSigned: Requires that all scripts and configuration files downloaded from the internet be signed by a trusted publisher. Locally created scripts do not need to be signed.
- Restricted: Disallows the execution of all scripts and configuration files, regardless of their origin. This is the most secure execution policy.
- Unrestricted: Allows the execution of all scripts and configuration files without any restrictions. This is the least secure execution policy.
- Bypass: Skips the execution policy check entirely, allowing all scripts to run. This is typically used for troubleshooting and development purposes.
- Undefined: Represents an undefined or unrecognized execution policy.
Execution Policy Scopes
PowerShell execution policies can be applied at different scopes, which determine the scope of the policy’s effect. The available execution policy scopes are:
- MachinePolicy: This scope sets the execution policy for all users and processes on the machine. It is defined by the Group Policy setting and applies to all users and processes on the machine.
- UserPolicy: This scope sets the execution policy for all users on the machine. It is also defined by the Group Policy setting and applies to all users on the machine.
- Process: This scope sets the execution policy for the current PowerShell process only. It is not saved or persisted.
- CurrentUser: This scope sets the execution policy for the current user. It applies to the current user only and is saved and persisted.
- LocalMachine: This scope sets the execution policy for all users on the machine. It applies to all users on the machine and is saved and persisted.
Note. If the execution policy for Process, CurrentUser, and LocalMachine scopes is set to Undefined, the effective policy applied to that scope is Restricted. If the MachinePolicy and UserPolicy scopes are set to Undefined, it means that they are not configured via Group Policy Objects and affect nothing.
Execution Policy Order of Precedence
When determining the effective execution policy, PowerShell follows a specific order of precedence. The execution policy order of precedence, from highest to lowest, is as follows:
- MachinePolicy
- UserPolicy
- Process
- CurrentUser
- LocalMachine
PowerShell checks the execution policy at each scope and applies the policy from the scope with the highest precedence. If no execution policy is defined at a particular scope, PowerShell moves to the next scope in the order of precedence.
To view the list of execution policies at each scope, you can run the Get-ExecutionPolicy -List command. This command displays the execution policies for all available scopes and helps you understand the order in which the policies are applied.
For example, the below execution policy list is the default on a Windows 11 computer.
How Does PowerShell Recognize a Remote Script?
In the previous section (Execution Policy Types), we discussed that the RemoteSigned policy requires all scripts “coming from the Internet” to have a digital signature (related post. How to Sign PowerShell Script?).
But how does PowerShell recognize that a script came from the internet? By looking into the Stream information of the file. For example, I downloaded a script from the internet called Delete-IISLog.ps1.
To check whether this file came from an outside source, I’ll run the following command to list its streams.
Get-item .\Delete-IISLogs.ps1 -Stream *
As you can see, this file has two zones: $DATA and Zone.Identifier. The Zone.Identifier stream contains the zone information where the file was downloaded.
To display the Zone.Identifier stream, let’s run the following command.
Get-Content .\Delete-IISLogs.ps1 -Stream Zone.Identifier
As you can see, this file came from GitHub, which is categorized under ZoneID 3. Below is the ZoneID table for your reference.
ZoneID Zone
——- ———————
0 My Computer
1 Local Intranet Zone
2 Trusted sites Zone
3 Internet Zone
4 Restricted Sites Zone
Configuring the PowerShell Script Execution Policy
To set the execution policy for the PowerShell script, the command to run is the Set-ExecutionPolicy cmdlet.
The Set-ExecutionPolicy command configures the script execution policy on a system. It allows you to specify the level of trust required for executing PowerShell scripts. By setting the execution policy, you can control whether scripts can run and which types of scripts are allowed to execute.
Set-ExecutionPolicy Syntax
The syntax of the Set-ExecutionPolicy command is as follows:
Set-ExecutionPolicy [-ExecutionPolicy] <PolicyType> [-Scope <PolicyScope>]
Here, <PolicyType> represents the desired execution policy type, such as “Restricted,” “RemoteSigned,” “Unrestricted,” etc. The -Scope parameter is optional and allows you to define the scope at which the execution policy should be applied, such as the current user, local machine, process, etc. If not specified, the scope defaults to LocalMachine.
By running the Set-ExecutionPolicy command with the appropriate parameters, you can enforce a specific execution policy that aligns with your security requirements and organizational policies.
It’s important to note that changing the execution policy requires administrative privileges, and modifying the execution policy can have security implications. Therefore, it is recommended to carefully consider the desired execution policy and its impact before making any changes.
Set the Execution Policy of the Default Scope (LocalMachine)
To set the LocalMachine scope execution policy, you don’t need to specify the -Scope parameter. Without it, the default scope affected is LocalMachine.
First, let’s confirm the current PowerShell script execution policy.
Get-ExecutionPolicy -List
In this example, the LocalMachine execution policy is RemoteSigned.
Let’s change it to AllSigned.
Set-ExecutionPolicy -ExecutionPolicy AllSigned
As you can see below, only the LocalMachine scope has changed.
Note that you may get an error message similar to the one below.
Set-ExecutionPolicy: PowerShell updated your execution policy successfully, but the setting is overridden by a policy defined at a more specific scope. Due to the override, your shell will retain its current effective execution policy of RemoteSigned.
This error message is an informative message saying that the execution policy you changed is for a scope with lower precedence than your session’s current scope. In this example, the Process scope policy is set to RemoteSigned and will take precedence over the LocalMachine scope.
Set the Execution Policy of a Specific Scope
To change the execution policy of a specific scope, you must specify it with the -Scope parameter.
Set-ExecutionPolicy -Scope Process -ExecutionPolicy RemoteSigned Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned Set-ExecutionPolicy -Scope LocalMachine -ExecutionPolicy RemoteSigned # List all execution policies Get-ExecutionPolicy -List
Working Around the PowerShell Script Execution Policy
Remember that the PowerShell script execution policy is a safety feature, not a security measure. It can be bypassed or ignored if the user context has administrative privileges.
In some cases, you may need to work around the PowerShell script execution policy, especially when running scripts from untrusted sources or during development and testing. Here are a couple of methods to work around the execution policy.
Using the -ExecutionPolicy Bypass Parameter
Without changing the PowerShell script execution policy, you can bypass the execution policy check using the -ExecutionPolicy Bypass parameter when running PowerShell scripts. This parameter overrides the current execution policy for the duration of the script execution.
With this method, you’re starting a new PowerShell process with the Bypass execution policy.
PowerShell.exe -ExecutionPolicy Bypass -File <ScriptPath>
Replace <ScriptPath> with the path to the PowerShell script you want to execute.
In this example, running scripts is disabled because the execution policy is Restricted. When I call the script directly in my PowerShell session, I get the error saying, “File C:\demo.ps1 cannot be loaded because running scripts is disabled on this system.”
As a workaround, I can run the following command instead. This command starts a new instance of Windows PowerShell.
powershell.exe -ExecutionPolicy Bypass -File C:\demo.ps1
You can also start an instance of PowerShell Core (7x). The executable name is pwsh.exe.
pwsh.exe -ExecutionPolicy Bypass -File C:\demo.ps1
Running PowerShell Code In Memory
Another way to work around the execution policy is to import the PowerShell script directly into memory and execute it without writing it to disk. This method can be helpful when you have a restricted execution policy that prevents the execution of external scripts.
$scriptContent = Get-Content -Path <ScriptPath> -Raw Invoke-Expression -Command $scriptContent
Replace <ScriptPath> with the path to the PowerShell script you want to execute.
$scriptContent = Get-Content -Path C:\demo.ps1 -Raw Invoke-Expression -Command $scriptContent
By importing the script into memory and using the Invoke-Expression cmdlet, you can execute the PowerShell code without triggering the execution policy check.
Conclusion
Managing PowerShell script execution policy is crucial for maintaining a balance between security and functionality. By understanding the different execution policy types, scopes, and order of precedence, you can effectively control script execution on your system.
Whether you need to check the current execution policy, set a new policy, or work around the policy for specific scenarios, the PowerShell Set-ExecutionPolicy cmdlet is the primary tool to manage the script execution policy efficiently.
Remember to choose the appropriate execution policy based on your security requirements and regularly review and update the policies to ensure the safety and reliability of your PowerShell scripts.