Skip to content

PowerShell Execution Policy

The execution policy controls whether PowerShell will run script files (.ps1). It is not a security boundary; a determined user can bypass it. What it does is stop a script from running by accident, such as a user double-clicking a malicious .ps1 from an email.

The policies

Policy Behavior Right for
Restricted No scripts run at all. Interactive commands still work. A workstation where nothing legitimate needs to run scripts. This is the Windows 11 default.
AllSigned Only scripts signed by a trusted publisher Locked-down environments
RemoteSigned Local scripts run; downloaded scripts must be signed Administrators' machines and servers that run maintenance scripts. This is the Server 2022 default.
Unrestricted Everything runs, with a warning for downloaded scripts Not on a production machine
Bypass Everything runs, no warnings Not on a production machine

Check

Get-ExecutionPolicy -List
        Scope ExecutionPolicy
        ----- ---------------
MachinePolicy       Undefined
   UserPolicy       Undefined
      Process       Undefined
  CurrentUser       Undefined
 LocalMachine    Unrestricted

The first defined scope from the top wins. Unrestricted at LocalMachine is the finding.

Set

Set-ExecutionPolicy Restricted -Scope LocalMachine -Force

On Server 2022, or if the README says the machine runs scripts:

Set-ExecutionPolicy RemoteSigned -Scope LocalMachine -Force

To enforce it through policy so it can't be changed from the prompt: gpedit.msc → Computer Configuration → Administrative Templates → Windows Components → Windows PowerShell → Turn on Script Execution: Enabled, Allow only signed scripts or Allow local scripts and remote signed scripts.

Verify

Get-ExecutionPolicy

Restricted or RemoteSigned.

Going further

Execution policy controls what runs. PowerShell Logging records what ran, which is what forensics questions need.

Try it

  1. Set the execution policy to RemoteSigned and try running an unsigned script you wrote. Then AllSigned. What changes?
  2. Turn on script block logging and run a script; find the event 4104 entries.

Build it

A pslogging.bat with the logging reg add lines, and a one-line PowerShell command that counts 4104 events today.

Next

Screen Lock