An execution policy is the PowerShell safety setting that determines under which conditions PowerShell loads configuration files and runs scripts, for example whether any script may run, only signed scripts may run, or scripts downloaded from the internet need a trusted digital signature. Within PowerShell & command line administration on Windows, it is the first obstacle a new user meets when a .ps1 file refuses to start.
The PowerShell execution policy is often misunderstood as a security boundary. It is not. Its purpose is to prevent accidental execution of untrusted scripts and to make the user’s intent explicit, while real enforcement against malicious code belongs to tools such as App Control for Business, AppLocker and endpoint protection.
Available execution policy values
PowerShell defines a small set of policy values, ranging from blocking all scripts to running everything without prompts. The value chosen controls script files, module script files and profiles, but it never blocks commands typed interactively at the prompt.
| Policy | Behavior | Typical use |
|---|---|---|
| Restricted | Allows individual commands, blocks all script files | Default on Windows client editions |
| AllSigned | Runs only scripts signed by a trusted publisher | High-assurance managed environments |
| RemoteSigned | Requires signatures only for scripts from the internet | Default on Windows Server, common for admins |
| Unrestricted | Runs all scripts, warns for internet files | Default on non-Windows platforms |
| Bypass | Runs everything without warnings or prompts | Automation hosts and embedded PowerShell |
| Undefined | No policy set in this scope | Falls back to the next scope or the default |
On Linux and macOS, PowerShell treats the policy as Unrestricted and cannot change it, because those platforms do not use the Windows zone information that the policy depends on.
Scopes and precedence
An execution policy can be set in five scopes, and the effective policy is the one from the highest-precedence scope that is not Undefined. Running Get-ExecutionPolicy -List shows every scope at once, which is the fastest way to diagnose why a script is blocked.
| Scope | Set by | Lifetime |
|---|---|---|
| MachinePolicy | Group Policy for all users of the computer | Until the policy is removed |
| UserPolicy | Group Policy for the current user | Until the policy is removed |
| Process | Parameter or environment variable of one session | Ends when the session closes |
| CurrentUser | Set-ExecutionPolicy by the user | Persistent in the user’s registry or settings |
| LocalMachine | Set-ExecutionPolicy by an administrator | Persistent for all users |
Group Policy scopes override all local choices, so an administrator who enforces AllSigned through a domain policy cannot be undone with Set-ExecutionPolicy. Changing the LocalMachine scope requires an elevated session, while the CurrentUser scope does not, which makes Set-ExecutionPolicy RemoteSigned -Scope CurrentUser the usual fix for a single developer.
How RemoteSigned detects internet files
RemoteSigned depends on the Mark of the Web, an alternate data stream named Zone.Identifier that browsers, email clients and some archive tools attach to downloaded files. When the stream marks a file as coming from the internet zone, PowerShell requires a valid Authenticode signature before running it.
A reviewed script can be released with the Unblock-File cmdlet, which removes the zone information. Files copied from a network share may be treated as remote depending on the intranet zone settings, and files extracted by tools that do not propagate the mark run as local files, which is one reason the policy is not a reliable defense.
The signature check itself is strict. PowerShell verifies that the script was signed by a certificate that chains to a trusted root, that the publisher is accepted, and that the file has not changed since signing. Editing even a single character of a signed script invalidates the signature, so signed scripts must be re-signed after every modification. The first time a script from a new publisher runs under AllSigned, PowerShell asks whether to trust that publisher, and the answer is stored in the Trusted Publishers certificate store.
Execution policy compared with real security controls
Anyone who can start PowerShell can bypass the policy, for example with powershell.exe -ExecutionPolicy Bypass -File script.ps1, by piping script text into the shell, or by pasting commands. Microsoft documents this behavior deliberately and states that the policy is not a security boundary. The table places the execution policy among the controls that actually restrict code.
| Control | What it enforces | Can a user bypass it |
|---|---|---|
| Execution policy | Whether script files load, and signing rules | Yes, easily |
| App Control for Business | Which code may run, enforced by the kernel | No, without administrative compromise |
| AppLocker | Allow lists for scripts and executables | Hard for standard users |
| Constrained Language Mode | Restricts dangerous language features | Enforced when application control is active |
| Script block logging | Records executed code for investigation | Detects rather than prevents |
| AMSI integration | Lets antimalware scan script content at runtime | Evasion attempts exist, but detection improves |
In practice, a sound configuration combines RemoteSigned or AllSigned for intent, application control for enforcement and logging for visibility. Relying on the execution policy alone gives a false sense of protection.
Choosing and setting a policy
The right choice depends on who writes the scripts and how they are distributed. Organizations with an internal code-signing certificate can use AllSigned and sign scripts with Set-AuthenticodeSignature as part of their release process. Most administrators and developers work comfortably with RemoteSigned.
- Check before changing: run
Get-ExecutionPolicy -Listto see which scope wins. - Prefer the narrowest scope, such as CurrentUser or Process, over LocalMachine.
- Avoid Unrestricted and Bypass as permanent settings on workstations.
- Sign production scripts so that AllSigned remains possible later.
- Remember the two editions: Windows PowerShell 5.1 and PowerShell 7 store their policies separately.
Understanding it simply
The execution policy is like a safety catch on a power tool. It stops you from running a script by accident, especially one you just downloaded, but anyone who really wants to use the tool can release the catch.
On a typical Windows computer, the catch is fully on, so scripts do not run at all until you change the setting. Many people choose a middle setting that allows their own scripts and asks for a trusted signature on scripts from the internet.
Applied in practice
A systems administrator at a school district writes a PowerShell script that creates student accounts each August. On a new Windows 11 laptop, the script fails with a message that running scripts is disabled. Get-ExecutionPolicy -List shows Restricted as the effective policy, because no scope is defined.
The administrator runs Set-ExecutionPolicy RemoteSigned -Scope CurrentUser, and the local script now runs. A colleague’s script downloaded from the internal file portal is still blocked because it carries the Mark of the Web. After reviewing its code, the administrator unblocks it. For the next school year, the team obtains a code-signing certificate and moves to AllSigned through Group Policy, so only reviewed and signed scripts run on staff devices.