The Situation
It's late. You're trying to run a deployment script, activate a Python virtual environment, or kick off a setup script a teammate just sent you. You type the command, hit Enter, and instead of progress โ you get this:
File C:\scripts\deploy.ps1 cannot be loaded because running scripts is disabled on this system.
For more information, see about_Execution_Policies at https://go.microsoft.com/fwlink/?LinkID=135170.
The script didn't run. Nothing was deployed. Your colleague's machine works fine, but yours won't budge.
PowerShell's execution policy is blocking you โ a security feature that controls which scripts are allowed to run. Windows locks it down by default. Five minutes from now, you'll have this fixed.
Understand What's Happening (30 seconds)
PowerShell has four execution policy levels that matter here:
- Restricted โ No scripts run at all. Default on client Windows editions (Windows 10/11).
- AllSigned โ Only scripts signed by a trusted publisher run.
- RemoteSigned โ Local scripts run freely; downloaded scripts need a signature.
- Unrestricted โ All scripts run, with a prompt for downloaded ones.
Nine times out of ten, this error means your policy is stuck on Restricted.
Check Your Current Policy First
Open PowerShell (not CMD) and run:
Get-ExecutionPolicy -List
You'll see output like this:
Scope ExecutionPolicy
----- ---------------
MachinePolicy Undefined
UserPolicy Undefined
Process Undefined
CurrentUser Undefined
LocalMachine Restricted
The most specific scope wins. LocalMachine showing Restricted with nothing else set? That's your culprit.
One caveat: if MachinePolicy or UserPolicy shows a value, that's Group Policy talking โ and you can't override it without admin access or a GPO change. Jump to Solution 3 if that's your situation.
Solution 1: Set Execution Policy for Current User (Recommended)
Start here. This only affects your user account, requires no UAC prompt, and works on most machines without admin rights.
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
RemoteSigned hits the right balance: your own scripts run freely, downloaded ones need a signature. That signature requirement is what catches actual malware โ so you're not opening a security hole by using it.
Solution 2: Set for the Entire Machine (Requires Admin)
Setting up a developer workstation or a CI/CD runner where all users need script access? Run PowerShell as Administrator, then:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope LocalMachine
PowerShell will ask you to confirm. Type Y and press Enter. Every user on the machine can now run scripts.
Solution 3: Bypass for a Single Session (No Admin, No Permanent Change)
Need to run one script right now without touching anything permanently? Use the Process scope:
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process
This only applies to the current PowerShell window. Close it, and the restriction comes back. Works even on Group Policy-locked machines โ GPO doesn't control per-process policy.
Solution 4: Bypass Inline for a Single Script
Another option: pass the execution policy directly when launching PowerShell:
powershell.exe -ExecutionPolicy Bypass -File .\your-script.ps1
From PowerShell 7:
pwsh -ExecutionPolicy Bypass -File .\your-script.ps1
Ideal for batch files, CI/CD pipelines, or Windows Task Scheduler jobs where you can't control the system policy. Jenkins and GitHub Actions pipelines often use exactly this pattern.
Solution 5: Unblock a Specific Downloaded File
Here's the one people miss: sometimes the execution policy isn't the real problem. Windows silently marks files downloaded from the internet as potentially unsafe โ and that mark alone can block them, regardless of your policy setting.
Check whether your script has this mark:
Get-Item .\your-script.ps1 | Select-Object -ExpandProperty Attributes
If the file has a Zone.Identifier alternate data stream, remove it:
Unblock-File -Path .\your-script.ps1
That's it. No policy change needed. Windows stops treating the file as untrusted, and PowerShell runs it without complaint.
Verify the Fix
After any of the above, confirm the policy looks right:
Get-ExecutionPolicy -List
Then run your script again. It should work now.
For the Unblock-File approach, double-check the stream is gone:
Get-Item .\your-script.ps1 -Stream *
Zone.Identifier should no longer appear in the output.
When Nothing Works: Group Policy Is Overriding You
If MachinePolicy or UserPolicy shows a restricted value, your org's Group Policy is enforcing it. Set-ExecutionPolicy will appear to succeed โ but revert the moment you check again.
Your options:
- Use
-Scope Processor the inline-ExecutionPolicy Bypassflag. Group Policy doesn't block either of these. - Talk to your sysadmin about a GPO exception for developer machines.
- Use
Invoke-Expressionoriexto pipe script content โ but only for code you've read and actually trust.
Lessons Learned
- Avoid
Unrestrictedon any machine running untrusted code.RemoteSignedis the sensible default for developers. - On shared CI/CD runners, set
-ExecutionPolicy Bypassin the pipeline command itself. Don't permanently change system policy. - Shipping scripts to teammates? Sign them with a self-signed cert and include it in your repo. Solves this problem for good on
AllSignedmachines. Unblock-Fileis criminally underused. A surprising number of "execution policy" errors from downloaded scripts are actually zone identifier issues in disguise.

