---
title: "PowerShell: “running scripts is disabled on this system” (execution policy)"
description: A .ps1 file will not run and PowerShell says running scripts is disabled on this system. That is the execution policy, which is Restricted by default on Windows 10 and 11. Here is how to read the policy scopes, pick the narrowest fix (one run, your user, or the machine), deal with downloaded files and Group Policy, and why this is a safety rail, not a security boundary.
url: "https://keh-tech.net/kb/powershell-running-scripts-is-disabled-on-this-system/"
updated: "2026-10-05"
category: Troubleshooting
tags:
  - Execution Policy
  - Group Policy
  - PowerShell
  - Windows
  - Windows PowerShell
  - Windows Server
---

# PowerShell: “running scripts is disabled on this system” (execution policy)

You double-click or type the name of a PowerShell script and, instead of running, it fails in red:

```
File C:\Scripts\Get-Report.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.
    + CategoryInfo          : SecurityError: (:) [], PSSecurityException
    + FullyQualifiedErrorId : UnauthorizedAccess
```

It can show up in surprising places: a Python virtual environment's `activate.ps1`, an npm or other tool's `.ps1` shim, or your own PowerShell profile that fails to load every time you open a window. The cause is the same each time: the **execution policy**.

**Applies to:** Windows 10, Windows 11 and Windows Server, in Windows PowerShell 5.1 (`powershell.exe`) and PowerShell 7 (`pwsh.exe`). Execution policy is enforced on Windows only. On Linux and macOS PowerShell it reports `Unrestricted` and does nothing.

## What is going on

PowerShell has a setting called the *execution policy* that decides whether it loads scripts and profiles at all, and whether they have to be digitally signed. Microsoft describes it as a safety feature that helps stop you running a script by accident. The defaults, from Microsoft's documentation:

- **Windows 10 and 11 (clients):** `Restricted` in Windows PowerShell 5.1. You can type commands, but no `.ps1` script, module script or profile will run. This is the one that produces the error above.
- **Windows Server:** `RemoteSigned`. Local scripts run. Scripts downloaded from the internet must be signed or unblocked.
- **PowerShell 7 (`pwsh`):** Microsoft's PowerShell 7 documentation lists the default as `RemoteSigned` for Windows clients and servers. Windows PowerShell and PowerShell 7 keep **separate** settings, so changing one does not change the other. That is why a script can fail in one and work in the other.

The policy is not set in one place. It is evaluated at several **scopes**, and the first scope that has a value wins. In order of strength:

1. `MachinePolicy`: set by Group Policy for every user of the computer. Overrides everything below.
2. `UserPolicy`: set by Group Policy for the current user.
3. `Process`: this PowerShell session only, lost when it closes (stored in `$Env:PSExecutionPolicyPreference`). This is what `-ExecutionPolicy` on the command line sets.
4. `CurrentUser`: you only, saved for next time.
5. `LocalMachine`: everyone on the computer, the default scope of `Set-ExecutionPolicy`. Needs an elevated prompt.

If none of them is set, the effective policy falls back to the default above: `Restricted` on a Windows client.

**The execution policy is not a security boundary.** Microsoft says so in the documentation: someone who cannot run a script can paste its contents into the console. It protects you from clicking something by mistake, not from a determined user or from malware. That is the reason to choose the narrowest setting that does the job and not to treat any setting as a lock.

## Diagnosis

### 1. Which shell are you in, and what does it think the policy is?

```
$PSVersionTable.PSVersion
Get-ExecutionPolicy
Get-ExecutionPolicy -List
```

A `Major` version of 5 is Windows PowerShell (`powershell.exe`). 7 or higher is PowerShell 7 (`pwsh.exe`). `Get-ExecutionPolicy` alone gives the *effective* policy. The list shows every scope. Microsoft's example looks like this:

```
        Scope ExecutionPolicy
        ----- ---------------
MachinePolicy       Undefined
   UserPolicy       Undefined
      Process       Undefined
  CurrentUser    RemoteSigned
 LocalMachine       AllSigned
```

Read it top to bottom. The first row that is not `Undefined` is the effective policy (here `RemoteSigned`, from `CurrentUser`, which beats `LocalMachine`). Two results matter most:

- **Everything `Undefined`:** nothing is set, so you are on the default, `Restricted` on a Windows client. Local fix.
- **`MachinePolicy` or `UserPolicy` is not `Undefined`:** Group Policy ("Turn on Script Execution") owns the setting. Your changes at the other scopes will not take effect.

### 2. Is it "disabled" or "not digitally signed"?

The two messages mean different things:

- **"running scripts is disabled on this system"**: the policy is `Restricted`, so no script runs, signed or not.
- **"is not digitally signed. The script will not execute on the system"**: the policy lets scripts run (`RemoteSigned` or `AllSigned`) but this file does not qualify. With `RemoteSigned` that almost always means the file came from the internet and is marked as such. See the Unblock-File step.

To see whether a file is marked as downloaded (Windows adds a `Zone.Identifier` alternate data stream, value 3 for the internet):

```
Get-Item .\script.ps1 -Stream Zone.Identifier -ErrorAction SilentlyContinue
Get-Content .\script.ps1 -Stream Zone.Identifier
```

No output means the file is not marked.

## Root cause

The effective execution policy is `Restricted` (the Windows client default, or set by Group Policy), so PowerShell will not load the script. Nothing is wrong with the script or with Windows. Fix it at the smallest scope that works: one run, then your own account, then the machine, and never past a Group Policy that is deliberately set.

## The fix

### Option 1: run this one script once (no setting changes)

```
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\script.ps1
```

The `-ExecutionPolicy` parameter sets the `Process` scope for that new session and its children. Nothing is saved. For PowerShell 7 use `pwsh.exe` in place of `powershell.exe`. It is also the right pattern for scheduled tasks, deployment tools and batch files. Microsoft notes that it does not override a Group Policy.

To change only the PowerShell window you are already in:

```
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process
```

### Option 2: allow local scripts for your account (recommended)

```
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
```

No elevation is needed. Answer `Y` to the prompt. `RemoteSigned` lets scripts you wrote or copied locally run, and still requires a signature (or unblocking) for files that came from the internet.

### Option 3: for every user on the machine

Open PowerShell with **Run as administrator**, then:

```
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope LocalMachine
```

`LocalMachine` is the default scope, so this is the same as leaving `-Scope` off. Use this on a server or a shared admin machine. For your own PC, option 2 touches less.

### If the script is "not digitally signed": unblock it

Read the script first. `Unblock-File` removes the internet mark, and from then on PowerShell treats the file as local.

```
Unblock-File -Path .\script.ps1

# a whole folder you have already reviewed; -WhatIf first shows what it would touch
Get-ChildItem .\Scripts -Filter *.ps1 | Unblock-File -WhatIf
```

It does not change the execution policy. Microsoft's page for the cmdlet says it does the same thing as ticking **Unblock** in the file's Properties dialog in File Explorer. Files fetched with `curl.exe`, `Invoke-WebRequest` or `Invoke-RestMethod` may not be marked at all.

### If Group Policy is setting it

When `MachinePolicy` or `UserPolicy` has a value, `Set-ExecutionPolicy` may print something like *"PowerShell updated your local preference successfully, but the setting is overridden by the Group Policy applied to your system"* and the effective policy stays as it was. That is Group Policy doing its job. The change belongs in the GPO ("Turn on Script Execution" under Administrative Templates, Windows Components, Windows PowerShell), made by whoever manages it. A script that must run on managed machines should be signed and run under `AllSigned` or `RemoteSigned`, not bypassed.

## Verification

```
Get-ExecutionPolicy -List
.\script.ps1
```

After option 2 the `CurrentUser` row should read `RemoteSigned` and the effective policy should match, unless a stronger scope above it overrides. Then the script should simply run. If a command appears to succeed but nothing changes, look at the list again: a more powerful scope (`Process`, or either Group Policy row) is winning.

## Notes

- **Do not use `Unrestricted` or edit the registry.** `RemoteSigned` covers local and unblocked scripts, and `Set-ExecutionPolicy` is the supported way to change it. In Windows PowerShell the values live under `HKLM` and `HKCU` `\Software\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell`. In PowerShell 7 they are in a `powershell.config.json` file instead. Editing them by hand gains nothing.
- **Bypass versus Unrestricted.** `Bypass` blocks nothing and warns about nothing. `Unrestricted` runs everything but warns before running scripts that came from outside the local intranet zone. Neither belongs as a permanent machine setting.
- **Scripts on a network share.** Microsoft notes that where UNC paths are not told apart from internet paths, a script on `\\server\share` may be refused under `RemoteSigned`. Copy it locally or sign it.
- **Logon scripts and Server Core.** Checking a file's zone needs the Windows shell. On Server Core, Nano Server, or a logon script that starts before the desktop is ready, the check can fail with `AuthorizationManager check failed`. Microsoft says `Bypass` or `AllSigned` avoids the zone check.
- **Different shell, different setting.** If a script worked in Windows PowerShell and fails in `pwsh` (or the other way round), compare `Get-ExecutionPolicy -List` in both.

**Group Policy fighting you, or a signing question?** Post the output of `Get-ExecutionPolicy -List` in [The Patch Panel](/community/help/) and we will work through it. The best answer earns points on [Top of the Stack](/leaderboard/).
