Execution policy

Also known as: PowerShell execution policy

On this page 7

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.

PolicyBehaviorTypical use
RestrictedAllows individual commands, blocks all script filesDefault on Windows client editions
AllSignedRuns only scripts signed by a trusted publisherHigh-assurance managed environments
RemoteSignedRequires signatures only for scripts from the internetDefault on Windows Server, common for admins
UnrestrictedRuns all scripts, warns for internet filesDefault on non-Windows platforms
BypassRuns everything without warnings or promptsAutomation hosts and embedded PowerShell
UndefinedNo policy set in this scopeFalls back to the next scope or the default
Execution policy values and their behavior

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.

ScopeSet byLifetime
MachinePolicyGroup Policy for all users of the computerUntil the policy is removed
UserPolicyGroup Policy for the current userUntil the policy is removed
ProcessParameter or environment variable of one sessionEnds when the session closes
CurrentUserSet-ExecutionPolicy by the userPersistent in the user’s registry or settings
LocalMachineSet-ExecutionPolicy by an administratorPersistent for all users
Execution policy scopes in order of precedence

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.

ControlWhat it enforcesCan a user bypass it
Execution policyWhether script files load, and signing rulesYes, easily
App Control for BusinessWhich code may run, enforced by the kernelNo, without administrative compromise
AppLockerAllow lists for scripts and executablesHard for standard users
Constrained Language ModeRestricts dangerous language featuresEnforced when application control is active
Script block loggingRecords executed code for investigationDetects rather than prevents
AMSI integrationLets antimalware scan script content at runtimeEvasion attempts exist, but detection improves
Controls that limit PowerShell code

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 -List to 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.