{"id":651,"date":"2026-08-18T23:51:19","date_gmt":"2026-08-18T23:51:19","guid":{"rendered":"https:\/\/windows-vps.org\/blog\/?p=651"},"modified":"2026-08-18T23:51:19","modified_gmt":"2026-08-18T23:51:19","slug":"powershell-execution-policy-windows-server-script-signing","status":"publish","type":"post","link":"https:\/\/windows-vps.org\/blog\/powershell-execution-policy-windows-server-script-signing\/","title":{"rendered":"PowerShell Execution Policy on Windows Server: RemoteSigned vs AllSigned vs Unrestricted"},"content":{"rendered":"<p class=\"wp-block-paragraph\">&#8220;Running scripts is disabled on this system&#8221; is the error every new Windows Server admin meets on day one. The cause is the execution policy, and the fix is rarely &#8220;set it to Unrestricted.&#8221; Execution policy is not a security boundary &#8211; a user can bypass it trivially &#8211; but it is a useful guardrail that stops accidental script execution and enforces a signing workflow. On an internet-facing VPS, how you configure it matters.<\/p>\n<h2 class=\"wp-block-heading\">The policy levels and what they actually do<\/h2>\n<figure class=\"wp-block-table\"><table><thead><tr><th>Policy<\/th><th>Default on<\/th><th>Behavior<\/th><\/tr><\/thead><tbody><tr><td>Restricted<\/td><td>Windows clients<\/td><td>No scripts run at all; interactive commands only<\/td><\/tr><tr><td>RemoteSigned<\/td><td>Windows Server<\/td><td>Local scripts run; downloaded scripts must be signed or unblocked<\/td><\/tr><tr><td>AllSigned<\/td><td>&#8211;<\/td><td>Every script must carry a valid signature<\/td><\/tr><tr><td>Unrestricted<\/td><td>&#8211;<\/td><td>All scripts run; downloaded ones prompt once (and are not blocked)<\/td><\/tr><tr><td>Bypass<\/td><td>&#8211;<\/td><td>Nothing is checked; use only for one-off bootstrapping<\/td><\/tr><tr><td>Undefined<\/td><td>&#8211;<\/td><td>No policy set at this scope; falls through to the next scope<\/td><\/tr><\/tbody><\/table><\/figure>\n<p class=\"wp-block-paragraph\">RemoteSigned is the sensible default for a server: scripts you write on the box run, and anything that arrived from the internet is blocked until it is signed or explicitly unblocked. The mechanism is the Mark of the Web: files downloaded through a browser carry a <code>Zone.Identifier<\/code> alternate data stream, and RemoteSigned refuses to run scripts that carry it.<\/p>\n<h2 class=\"wp-block-heading\">Checking and setting the policy<\/h2>\n<pre class=\"wp-block-code\"><code># See every scope and which one wins\nGet-ExecutionPolicy -List\n\n# Set for the machine (needs elevation)\nSet-ExecutionPolicy RemoteSigned -Scope LocalMachine\n\n# One-off bypass for a single command, no permanent change\npowershell -ExecutionPolicy Bypass -File .\\bootstrap.ps1\npwsh -ExecutionPolicy Bypass -File .\\bootstrap.ps1<\/code><\/pre>\n<p class=\"wp-block-paragraph\">Scopes are evaluated in a fixed order: <strong>MachinePolicy, UserPolicy, Process, CurrentUser, LocalMachine<\/strong>. The first one that is set wins. GPO policies (<code>MachinePolicy<\/code>\/<code>UserPolicy<\/code>) always override everything else, which is how a domain admin pins the setting on managed servers. On a standalone VPS, <code>LocalMachine<\/code> is the scope to use so the policy survives reboots and applies to scheduled tasks and service accounts, not just your interactive session.<\/p>\n<h2 class=\"wp-block-heading\">Why you should not reach for Unrestricted<\/h2>\n<p class=\"wp-block-paragraph\">Unrestricted on an exposed server means any script that lands on disk &#8211; via a dropped web shell, a compromised upload folder, or a phishing-delivered payload &#8211; executes without a prompt when invoked. The cost of RemoteSigned is a few seconds of <code>Unblock-File<\/code> when a legitimately downloaded script needs to run:<\/p>\n<pre class=\"wp-block-code\"><code># Only for files you have reviewed\nUnblock-File -Path &quot;C:\\tools\\Get-IISLogStats.ps1&quot;\n# or clear the Zone.Identifier stream directly\nRemove-Item &quot;C:\\tools\\Get-IISLogStats.ps1&quot; -Stream Zone.Identifier<\/code><\/pre>\n<p class=\"wp-block-paragraph\">Note that <code>curl.exe<\/code> and <code>Invoke-WebRequest<\/code> do not add the Mark of the Web, while browsers and <code>Start-BitsTransfer<\/code> do. A script pulled with curl will run under RemoteSigned even though a browser download of the same file would not &#8211; keep that in mind when auditing how files actually arrived.<\/p>\n<h2 class=\"wp-block-heading\">Signing scripts for production automation<\/h2>\n<p class=\"wp-block-paragraph\">For scheduled tasks and unattended automation, move from &#8220;unblock the file&#8221; to &#8220;sign the script.&#8221; Create a code-signing certificate and sign your own scripts:<\/p>\n<pre class=\"wp-block-code\"><code>New-SelfSignedCertificate -Type CodeSigningCert `\n  -Subject &quot;CN=Ops Scripts (Internal)&quot; `\n  -CertStoreLocation Cert:\\LocalMachine\\My\n\n$cert = Get-ChildItem Cert:\\LocalMachine\\My | Where-Object Subject -like &quot;*Ops Scripts*&quot; | Select-Object -First 1\nSet-AuthenticodeSignature -FilePath &quot;C:\\scripts\\DailyBackup.ps1&quot; -Certificate $cert\n\n# verify\nGet-AuthenticodeSignature &quot;C:\\scripts\\DailyBackup.ps1&quot;<\/code><\/pre>\n<p class=\"wp-block-paragraph\">A self-signed certificate keeps the script running under RemoteSigned on the same machine, but other servers will not trust it until you add it to their Trusted Publishers store. For scripts that cross machines, buy a code-signing certificate from a public CA and sign in your build pipeline instead of on the server.<\/p>\n<h2 class=\"wp-block-heading\">Execution policy vs. Constrained Language Mode<\/h2>\n<p class=\"wp-block-paragraph\">Do not confuse execution policy with language mode. If AppLocker or Windows Defender Application Control (WDAC) policies are active, PowerShell runs in Constrained Language Mode regardless of the execution policy: scripts execute, but they are restricted to a safe subset of the language. On a locked-down VPS, that is the stronger control &#8211; execution policy just keeps the careless stuff from running at all.<\/p>\n<h2 class=\"wp-block-heading\">A sane baseline for a small Windows VPS<\/h2>\n<ul class=\"wp-block-list\"><li><code>Set-ExecutionPolicy RemoteSigned -Scope LocalMachine<\/code> right after first login.<\/li><li>Leave Unrestricted and Bypass out of permanent configuration; use <code>-ExecutionPolicy Bypass<\/code> per-invocation when bootstrapping.<\/li><li>Unblock files only after review; prefer signing for anything that runs unattended.<\/li><li>Check <code>Get-ExecutionPolicy -List<\/code> after domain join or GPO changes &#8211; policy may silently change.<\/li><li>Audit occasionally: <code>Get-ChildItem -Recurse -Filter *.ps1 | Unblock-File -WhatIf<\/code> shows what still carries the Mark of the Web.<\/li><\/ul>\n<p class=\"wp-block-paragraph\">Execution policy is ten minutes of setup that prevents a class of &#8220;how did that script even run&#8221; incidents. If you are setting up a fresh server and want a guided first-hour sequence, the <a href=\"https:\/\/windows-vps.org\/#features\">feature checklist on our site<\/a> on our site covers adjacent hardening steps, and you can compare managed vs. self-managed options on the <a href=\"https:\/\/windows-vps.org\/#providers\">Windows VPS comparison table on our site<\/a> before you commit.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>&#8220;Running scripts is disabled on this system&#8221; is the error every new Windows Server admin meets on day one. The cause is the execution policy, and the fix is rarely &#8220;set it to Unrestricted.&#8221; Execution policy is not a security boundary &#8211; a user can bypass it trivially &#8211; but it is a useful guardrail &#8230; <a title=\"PowerShell Execution Policy on Windows Server: RemoteSigned vs AllSigned vs Unrestricted\" class=\"read-more\" href=\"https:\/\/windows-vps.org\/blog\/powershell-execution-policy-windows-server-script-signing\/\" aria-label=\"Read more about PowerShell Execution Policy on Windows Server: RemoteSigned vs AllSigned vs Unrestricted\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":0,"footnotes":""},"categories":[5],"tags":[],"class_list":["post-651","post","type-post","status-publish","format-standard","hentry","category-tutorials-guides"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.1 (Yoast SEO v26.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>PowerShell Execution Policy on Windows Server: RemoteSigned vs AllSigned vs Unrestricted - Windows VPS Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/windows-vps.org\/blog\/powershell-execution-policy-windows-server-script-signing\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"PowerShell Execution Policy on Windows Server: RemoteSigned vs AllSigned vs Unrestricted\" \/>\n<meta property=\"og:description\" content=\"PowerShell Execution Policy on Windows Server: RemoteSigned vs AllSigned vs Unrestricted\" \/>\n<meta property=\"og:url\" content=\"https:\/\/windows-vps.org\/blog\/powershell-execution-policy-windows-server-script-signing\/\" \/>\n<meta property=\"og:site_name\" content=\"Windows VPS Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-08-18T23:51:19+00:00\" \/>\n<meta name=\"author\" content=\"windows-vps\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"windows-vps\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/windows-vps.org\/blog\/powershell-execution-policy-windows-server-script-signing\/\",\"url\":\"https:\/\/windows-vps.org\/blog\/powershell-execution-policy-windows-server-script-signing\/\",\"name\":\"PowerShell Execution Policy on Windows Server: RemoteSigned vs AllSigned vs Unrestricted - Windows VPS Blog\",\"isPartOf\":{\"@id\":\"https:\/\/windows-vps.org\/blog\/#website\"},\"datePublished\":\"2026-08-18T23:51:19+00:00\",\"author\":{\"@id\":\"https:\/\/windows-vps.org\/blog\/#\/schema\/person\/44caceed916d0db318aa08d5623a7a58\"},\"breadcrumb\":{\"@id\":\"https:\/\/windows-vps.org\/blog\/powershell-execution-policy-windows-server-script-signing\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/windows-vps.org\/blog\/powershell-execution-policy-windows-server-script-signing\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/windows-vps.org\/blog\/powershell-execution-policy-windows-server-script-signing\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/windows-vps.org\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"PowerShell Execution Policy on Windows Server: RemoteSigned vs AllSigned vs Unrestricted\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/windows-vps.org\/blog\/#website\",\"url\":\"https:\/\/windows-vps.org\/blog\/\",\"name\":\"Windows VPS Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/windows-vps.org\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/windows-vps.org\/blog\/#\/schema\/person\/44caceed916d0db318aa08d5623a7a58\",\"name\":\"windows-vps\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/windows-vps.org\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/3f2573db5afcd1a6ab9abcc5d48fc8e42584bc87ab9d98cc156e5b2097766dd9?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/3f2573db5afcd1a6ab9abcc5d48fc8e42584bc87ab9d98cc156e5b2097766dd9?s=96&d=mm&r=g\",\"caption\":\"windows-vps\"},\"sameAs\":[\"https:\/\/windows-vps.org\/blog\"],\"url\":\"https:\/\/windows-vps.org\/blog\/author\/myxiechengxuan\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"PowerShell Execution Policy on Windows Server: RemoteSigned vs AllSigned vs Unrestricted - Windows VPS Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/windows-vps.org\/blog\/powershell-execution-policy-windows-server-script-signing\/","og_locale":"en_US","og_type":"article","og_title":"PowerShell Execution Policy on Windows Server: RemoteSigned vs AllSigned vs Unrestricted","og_description":"PowerShell Execution Policy on Windows Server: RemoteSigned vs AllSigned vs Unrestricted","og_url":"https:\/\/windows-vps.org\/blog\/powershell-execution-policy-windows-server-script-signing\/","og_site_name":"Windows VPS Blog","article_published_time":"2026-08-18T23:51:19+00:00","author":"windows-vps","twitter_card":"summary_large_image","twitter_misc":{"Written by":"windows-vps","Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/windows-vps.org\/blog\/powershell-execution-policy-windows-server-script-signing\/","url":"https:\/\/windows-vps.org\/blog\/powershell-execution-policy-windows-server-script-signing\/","name":"PowerShell Execution Policy on Windows Server: RemoteSigned vs AllSigned vs Unrestricted - Windows VPS Blog","isPartOf":{"@id":"https:\/\/windows-vps.org\/blog\/#website"},"datePublished":"2026-08-18T23:51:19+00:00","author":{"@id":"https:\/\/windows-vps.org\/blog\/#\/schema\/person\/44caceed916d0db318aa08d5623a7a58"},"breadcrumb":{"@id":"https:\/\/windows-vps.org\/blog\/powershell-execution-policy-windows-server-script-signing\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/windows-vps.org\/blog\/powershell-execution-policy-windows-server-script-signing\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/windows-vps.org\/blog\/powershell-execution-policy-windows-server-script-signing\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/windows-vps.org\/blog\/"},{"@type":"ListItem","position":2,"name":"PowerShell Execution Policy on Windows Server: RemoteSigned vs AllSigned vs Unrestricted"}]},{"@type":"WebSite","@id":"https:\/\/windows-vps.org\/blog\/#website","url":"https:\/\/windows-vps.org\/blog\/","name":"Windows VPS Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/windows-vps.org\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/windows-vps.org\/blog\/#\/schema\/person\/44caceed916d0db318aa08d5623a7a58","name":"windows-vps","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/windows-vps.org\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/3f2573db5afcd1a6ab9abcc5d48fc8e42584bc87ab9d98cc156e5b2097766dd9?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/3f2573db5afcd1a6ab9abcc5d48fc8e42584bc87ab9d98cc156e5b2097766dd9?s=96&d=mm&r=g","caption":"windows-vps"},"sameAs":["https:\/\/windows-vps.org\/blog"],"url":"https:\/\/windows-vps.org\/blog\/author\/myxiechengxuan\/"}]}},"_links":{"self":[{"href":"https:\/\/windows-vps.org\/blog\/wp-json\/wp\/v2\/posts\/651","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/windows-vps.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/windows-vps.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/windows-vps.org\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/windows-vps.org\/blog\/wp-json\/wp\/v2\/comments?post=651"}],"version-history":[{"count":1,"href":"https:\/\/windows-vps.org\/blog\/wp-json\/wp\/v2\/posts\/651\/revisions"}],"predecessor-version":[{"id":654,"href":"https:\/\/windows-vps.org\/blog\/wp-json\/wp\/v2\/posts\/651\/revisions\/654"}],"wp:attachment":[{"href":"https:\/\/windows-vps.org\/blog\/wp-json\/wp\/v2\/media?parent=651"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/windows-vps.org\/blog\/wp-json\/wp\/v2\/categories?post=651"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/windows-vps.org\/blog\/wp-json\/wp\/v2\/tags?post=651"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}