Setting execution policy to RemoteSigned protects you from scripts arriving by email. It does nothing about a script someone modified on the file share last Tuesday. If you want to know that what runs is what you wrote, you need signing.
If you already run an internal certificate authority, and most organisations with Active Directory do. This is a couple of hours of work, and it changes what execution policy is actually capable of enforcing.
Quick Facts
- Signing proves two things: who wrote the script, and that it hasn’t changed since.
- You need a certificate with the Code Signing enhanced key usage. A general-purpose certificate won’t do.
- Trust is distributed by publishing the signing certificate to Trusted Publishers via Group Policy.
AllSignedis the policy that makes signing meaningful.RemoteSignedonly checks downloaded files.- Timestamp your signatures, or every script breaks when the certificate expires.
Getting a code-signing certificate
From an internal CA, duplicate the built-in Code Signing template, allow the group who’ll sign scripts to enrol, and publish it. Then request it from the machine you’ll sign on:
# Request from your internal CA (certificate template must be published)
Get-Certificate -Template CodeSigning -CertStoreLocation Cert:\CurrentUser\My
# Confirm you have it
Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert
For testing without a CA, a self-signed certificate works and behaves identically. It just won’t be trusted anywhere you haven’t explicitly installed it:
New-SelfSignedCertificate -Subject 'CN=TGH Script Signing' -Type CodeSigningCert -CertStoreLocation Cert:\CurrentUser\My
Signing a script
$cert = Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert | Select-Object -First 1
Set-AuthenticodeSignature -FilePath .\Get-LowDiskSpace.ps1 -Certificate $cert `
-TimestampServer 'http://timestamp.digicert.com'
# Verify
Get-AuthenticodeSignature .\Get-LowDiskSpace.ps1 | Format-List Status, SignerCertificate
The timestamp server is not optional in practice. Without it, signatures become invalid the moment the certificate expires. Typically a year or two later, and every signed script stops running at once. With a timestamp, the signature stays valid because it proves the script was signed while the certificate was still good.
Signing appends a signature block to the end of the file. Edit the script afterwards, even by one character, and the signature no longer matches. Which is the entire point.
Distributing trust
A signature is only useful if machines trust the signer. Export the signing certificate’s public key and deploy it to two stores via Group Policy:
Quick Steps
- Export the certificate public key only as a
.cerfile. Never export the private key to a share. - Open a GPO, go to Computer Configuration, Policies, Windows Settings, Security Settings, Public Key Policies.
- Import the certificate into Trusted Publishers.
- Also import your CA’s root into Trusted Root Certification Authorities if it isn’t already there.
- Set execution policy to
AllSignedvia the PowerShell policy in the same GPO. - Test on one machine before scoping it broadly.
Get the order right: deploy the trust first, confirm it’s applied, and only then switch execution policy to AllSigned. Reversing that stops every script on every targeted machine.
The gotchas
- Editors can break signatures silently. Anything that alters line endings or re-encodes the file invalidates it. Sign as the last step before deployment.
- Encoding matters. Signing expects a consistent encoding; a script saved as UTF-8 with BOM and later rewritten without one will fail validation.
- Profile scripts count. Under
AllSigned, your own$PROFILEmust be signed too, or every session starts with an error. - Revocation checking needs the CRL to be reachable. Machines that can’t reach the distribution point can be slow to validate, or fail.
- Private key protection is the whole game. A stolen signing key means an attacker can sign scripts your estate trusts by policy.
Glossary
| Term | What it means |
| Authenticode | Microsoft’s code-signing technology, used by PowerShell for script signatures. |
| Code Signing EKU | An extended key usage marking a certificate as valid for signing code. |
| Trusted Publishers | The certificate store listing signers whose signed code is trusted. |
| Timestamp server | A service attesting when a signature was made, keeping it valid past certificate expiry. |
| CRL | Certificate Revocation List. How clients check whether a certificate has been revoked. |
AllSigned | Execution policy requiring every script to carry a trusted signature. |
Frequently asked questions
Do I need an internal CA to sign scripts?
No. A self-signed certificate works technically. But you’d have to install it on every machine that runs the scripts, which is exactly the distribution problem an internal CA already solves.
What happens when the signing certificate expires?
If you timestamped the signatures, nothing. They remain valid. If you didn’t, every script signed with it stops running under AllSigned. Always timestamp.
Can I sign scripts on a build server automatically?
Yes, and it’s the better pattern. Keep the private key on the build server (ideally in an HSM or the machine store with restricted access) and sign as a release step rather than on developer machines.
Does signing stop someone running a malicious script?
It stops unsigned and modified scripts under AllSigned. It doesn’t stop someone with a trusted signing certificate signing something bad, which is why protecting the private key matters more than the signing itself.
Why does my signed script fail after I edit it?
Because that’s the design. Any change invalidates the signature. Re-sign after every edit, and treat signing as the final step before deployment.
Gear We Recommend
Building out an internal PKI? Here’s the admin kit we use for lab and test work.
Browse our Admin Machine picks on AmazonAs an Amazon Associate, TechyGeeksHome earns from qualifying purchases
Disclosure: this post may contain affiliate links. If you buy through one of them, we may earn a small commission at no extra cost to you. We only recommend products we’ve tested or genuinely rate.
Discover more from TechyGeeksHome
Subscribe to get the latest posts sent to your email.