This is a Follow-up on the previous Blog Post here, on a new Dev machine

If you’re running PowerShell scripts like npm.ps1 and encounter this error:

A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider.

You’re not alone. This issue is common in environments where PowerShell’s execution policy is set to AllSigned. Fortunately, you can fix it by signing PowerShell scripts locally using a self-signed certificate.

In this guide, I’ll walk you through the entire process — from generating a certificate to signing and trusting the script — all without requiring internet access or external tools.


🔍 What Causes the “Untrusted Certificate” PowerShell Error?

PowerShell’s execution policies (such as AllSigned or RemoteSigned) are designed to prevent untrusted or unsigned scripts from running. If a script is digitally signed, but the signing certificate isn’t trusted by your machine, PowerShell will block it — even if the file is from a trusted source like Node.js.

This is common with files like:

C:\Program Files\nodejs\npm.ps1

You can check your current execution policy with:

Get-ExecutionPolicy -List

If it’s set to AllSigned, all scripts must have a trusted digital signature.


🔐 Step-by-Step: Sign PowerShell Scripts Locally (and Make Them Trusted)

✅ Step 1: Create a Self-Signed Code-Signing Certificate

Run this PowerShell command to create a certificate for local script signing:

New-SelfSignedCertificate `
  -CertStoreLocation Cert:\CurrentUser\My `
  -Subject "CN=Local Code Signing" `
  -KeyUsage DigitalSignature `
  -Type CodeSigningCert

This creates a code-signing certificate in your Current User certificate store.


🏢 Step 2: Trust the Certificate on Your Local Machine

To avoid trust errors when running signed scripts, you must add the certificate to both:

  • Trusted Root Certification Authorities
  • Trusted Publishers
$cert = Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert | Where-Object {
    $_.Subject -like "*Local Code Signing*"
}

# Add to Trusted Root
$storeRoot = New-Object System.Security.Cryptography.X509Certificates.X509Store "Root", "CurrentUser"
$storeRoot.Open("ReadWrite")
$storeRoot.Add($cert)
$storeRoot.Close()

# Add to Trusted Publishers
$storeTrusted = New-Object System.Security.Cryptography.X509Certificates.X509Store "TrustedPublisher", "CurrentUser"
$storeTrusted.Open("ReadWrite")
$storeTrusted.Add($cert)
$storeTrusted.Close()

🖊️ Step 3: Sign the PowerShell Script File

Use Set-AuthenticodeSignature to sign the .ps1 file you want to trust.

For example, to sign npm.ps1:

# Unblock the file first (if needed)
Unblock-File "C:\Program Files\nodejs\npm.ps1"

# Sign it using the local certificate
Set-AuthenticodeSignature `
  -FilePath "C:\Program Files\nodejs\npm.ps1" `
  -Certificate $cert

You should see a result like:

Status        : Valid
StatusMessage : Signature verified.

🧪 Step 4: Test the Script

Run the script to ensure it executes without any trust issues:

npm -v

If everything is configured correctly, PowerShell will now allow the signed script to run even under strict policies.


🧯 Optional: Trust the Certificate for All Users (Machine-Wide)

If you want all users on the machine to trust your signing certificate:

  1. Export the certificate: Export-Certificate -Cert $cert -FilePath "C:\Temp\LocalCodeSigning.cer"
  2. Open certlm.msc (Local Machine Certificates).
  3. Import the .cer file into:
    • Trusted Root Certification Authorities
    • Trusted Publishers

This ensures that your signed scripts are trusted system-wide.


🚀 Benefits of Locally Signed PowerShell Scripts

  • ✅ Run signed scripts without policy errors.
  • ✅ Maintain compliance with AllSigned or RemoteSigned execution policies.
  • ✅ Avoid bypassing execution policy with insecure workarounds.
  • ✅ Increase trust and traceability in automation environments.

🧠 Final Thoughts

Strict PowerShell execution policies are there to protect you — but they don’t have to be a roadblock. With a local code-signing certificate and a few simple steps, you can securely run trusted PowerShell scripts on your machine or across your organization.

Similar Posts

Leave a Reply