Fix “npx.ps1 Is Not Digitally Signed” in PowerShell
If you’re using Node.js, npm or npx on Windows and PowerShell suddenly refuses to run your commands with an error like this:
npx : File C:\Program Files\nodejs\npx.ps1 cannot be loaded.
The file C:\Program Files\nodejs\npx.ps1 is not digitally signed.
You cannot run this script on the current system.
CategoryInfo : SecurityError: (:) [], PSSecurityException
FullyQualifiedErrorId : UnauthorizedAccess
you’ve most likely run into a PowerShell Execution Policy restriction.
I encountered this while trying to run:
npx serve "C:\Projects\TypeRider" -l 3000
The problem wasn’t Node.js, npx, or the project.
PowerShell was blocking:
C:\Program Files\nodejs\npx.ps1
because the PowerShell script wasn’t digitally signed.
If your machine uses the stricter AllSigned execution policy, there are two good ways to deal with this:
- Use the
.cmdversion of npx and avoid the PowerShell script entirely. - Create your own trusted code-signing certificate and sign the Node.js PowerShell scripts.
Here’s how to do both.
First, Check Your PowerShell Execution Policy
Open PowerShell and run:
Get-ExecutionPolicy -List
You may see something similar to:
Scope ExecutionPolicy
----- ---------------
MachinePolicy Undefined
UserPolicy Undefined
Process Undefined
CurrentUser AllSigned
LocalMachine Undefined
The important one in this case is:
AllSigned
With AllSigned, PowerShell requires scripts to have a valid digital signature from a trusted publisher.
That includes scripts installed with Node.js such as:
C:\Program Files\nodejs\npm.ps1
C:\Program Files\nodejs\npx.ps1
So when you type:
npx
PowerShell may resolve the command to npx.ps1 and then refuse to execute it.
Solution 1: The Quick Fix — Use npx.cmd
Before changing anything on your computer, try this.
Instead of:
npx serve "C:\Projects\TypeRider" -l 3000
run:
npx.cmd serve "C:\Projects\TypeRider" -l 3000
That’s it.
Node.js normally installs Windows command wrappers alongside the PowerShell wrappers.
So instead of executing:
npx.ps1
you’re explicitly telling Windows to execute:
npx.cmd
This avoids the PowerShell script execution-policy problem entirely.
You can confirm which commands Windows can see with:
Get-Command npx -All
Depending on your Node installation, you should see entries for both the PowerShell and CMD versions.
For many developers, this is the best solution because you don’t have to weaken your PowerShell security policy or modify the Node installation.
But if you deliberately use AllSigned and want npm and npx to work normally from PowerShell, you can sign the scripts yourself.
Solution 2: Sign the Node.js PowerShell Scripts
The more permanent solution is to:
- Create a local code-signing certificate.
- Trust that certificate.
- Sign the Node.js PowerShell scripts.
- Verify the signatures.
This allows you to keep the stricter AllSigned execution policy.
Important
You’ll be modifying files under:
C:\Program Files\nodejs
so open PowerShell as Administrator.
Then paste the following complete script.
# ============================================================
# FIX NODE.JS / NPM / NPX POWERSHELL SIGNATURE ERRORS
#
# Fixes errors such as:
#
# npx.ps1 cannot be loaded.
# The file is not digitally signed.
#
# Intended for systems using the AllSigned execution policy.
# ============================================================
Write-Host ""
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host " Node.js PowerShell Code Signing Setup" -ForegroundColor Cyan
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host ""
# ------------------------------------------------------------
# 1. Show current PowerShell execution policies
# ------------------------------------------------------------
Write-Host "Current PowerShell execution policies:" -ForegroundColor Yellow
Get-ExecutionPolicy -List | Format-Table -AutoSize
Write-Host ""
# ------------------------------------------------------------
# 2. Certificate configuration
# ------------------------------------------------------------
$CertificateSubject = "CN=Local Node PowerShell Code Signing"
# ------------------------------------------------------------
# 3. Look for an existing certificate
# ------------------------------------------------------------
Write-Host "Looking for an existing code-signing certificate..." -ForegroundColor Yellow
$cert = Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert |
Where-Object {
$_.Subject -eq $CertificateSubject -and
$_.NotAfter -gt (Get-Date)
} |
Sort-Object NotAfter -Descending |
Select-Object -First 1
# ------------------------------------------------------------
# 4. Create certificate if one doesn't already exist
# ------------------------------------------------------------
if (-not $cert) {
Write-Host "No existing certificate found." -ForegroundColor Yellow
Write-Host "Creating a new self-signed code-signing certificate..." -ForegroundColor Yellow
$cert = New-SelfSignedCertificate `
-Type CodeSigningCert `
-Subject $CertificateSubject `
-CertStoreLocation "Cert:\CurrentUser\My" `
-KeyUsage DigitalSignature `
-KeyAlgorithm RSA `
-KeyLength 2048 `
-HashAlgorithm SHA256
Write-Host ""
Write-Host "Certificate created successfully." -ForegroundColor Green
}
else {
Write-Host "Existing certificate found." -ForegroundColor Green
}
Write-Host ""
Write-Host "Certificate:" -ForegroundColor Cyan
Write-Host "Subject : $($cert.Subject)"
Write-Host "Thumbprint : $($cert.Thumbprint)"
Write-Host "Expires : $($cert.NotAfter)"
Write-Host ""
# ------------------------------------------------------------
# 5. Trust certificate in CURRENT USER ROOT store
# ------------------------------------------------------------
Write-Host "Adding certificate to Trusted Root Certification Authorities..." -ForegroundColor Yellow
$rootStore = New-Object System.Security.Cryptography.X509Certificates.X509Store(
"Root",
"CurrentUser"
)
$rootStore.Open(
[System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite
)
try {
$existingRoot = $rootStore.Certificates |
Where-Object {
$_.Thumbprint -eq $cert.Thumbprint
}
if (-not $existingRoot) {
$rootStore.Add($cert)
Write-Host "Certificate added to Trusted Root." -ForegroundColor Green
}
else {
Write-Host "Certificate already exists in Trusted Root." -ForegroundColor Green
}
}
finally {
$rootStore.Close()
}
# ------------------------------------------------------------
# 6. Trust certificate as a Trusted Publisher
# ------------------------------------------------------------
Write-Host ""
Write-Host "Adding certificate to Trusted Publishers..." -ForegroundColor Yellow
$publisherStore = New-Object System.Security.Cryptography.X509Certificates.X509Store(
"TrustedPublisher",
"CurrentUser"
)
$publisherStore.Open(
[System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite
)
try {
$existingPublisher = $publisherStore.Certificates |
Where-Object {
$_.Thumbprint -eq $cert.Thumbprint
}
if (-not $existingPublisher) {
$publisherStore.Add($cert)
Write-Host "Certificate added to Trusted Publishers." -ForegroundColor Green
}
else {
Write-Host "Certificate already exists in Trusted Publishers." -ForegroundColor Green
}
}
finally {
$publisherStore.Close()
}
# ------------------------------------------------------------
# 7. Node.js directory
# ------------------------------------------------------------
$NodePath = "C:\Program Files\nodejs"
if (-not (Test-Path $NodePath)) {
Write-Host ""
Write-Host "ERROR: Node.js directory was not found:" -ForegroundColor Red
Write-Host $NodePath -ForegroundColor Red
throw "Node.js installation directory not found."
}
Write-Host ""
Write-Host "Node.js directory found:" -ForegroundColor Green
Write-Host $NodePath
# ------------------------------------------------------------
# 8. Find all Node.js PowerShell wrapper scripts
# ------------------------------------------------------------
Write-Host ""
Write-Host "Looking for Node.js PowerShell scripts..." -ForegroundColor Yellow
$NodeScripts = Get-ChildItem `
-Path $NodePath `
-Filter "*.ps1" `
-File
if (-not $NodeScripts) {
throw "No PowerShell scripts were found in $NodePath"
}
Write-Host ""
Write-Host "Scripts found:" -ForegroundColor Cyan
$NodeScripts | ForEach-Object {
Write-Host " $($_.FullName)"
}
# ------------------------------------------------------------
# 9. Unblock and sign each Node.js PowerShell script
# ------------------------------------------------------------
Write-Host ""
Write-Host "Signing Node.js PowerShell scripts..." -ForegroundColor Yellow
foreach ($script in $NodeScripts) {
Write-Host ""
Write-Host "Processing:" -ForegroundColor Cyan
Write-Host $script.FullName
try {
Unblock-File `
-Path $script.FullName `
-ErrorAction SilentlyContinue
$signature = Set-AuthenticodeSignature `
-FilePath $script.FullName `
-Certificate $cert `
-HashAlgorithm SHA256
if ($signature.Status -eq "Valid") {
Write-Host "SIGNED SUCCESSFULLY" -ForegroundColor Green
}
else {
Write-Host "SIGNATURE RESULT:" -ForegroundColor Yellow
Write-Host $signature.Status
Write-Host $signature.StatusMessage
}
}
catch {
Write-Host "FAILED TO SIGN:" -ForegroundColor Red
Write-Host $_.Exception.Message -ForegroundColor Red
}
}
# ------------------------------------------------------------
# 10. Verify signatures
# ------------------------------------------------------------
Write-Host ""
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host " Signature Verification" -ForegroundColor Cyan
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host ""
foreach ($script in $NodeScripts) {
$signature = Get-AuthenticodeSignature `
-FilePath $script.FullName
Write-Host "$($script.Name)" -ForegroundColor Cyan
Write-Host " Status : $($signature.Status)"
if ($signature.SignerCertificate) {
Write-Host " Signed : $($signature.SignerCertificate.Subject)"
}
Write-Host ""
}
# ------------------------------------------------------------
# 11. Specifically verify npm.ps1 and npx.ps1
# ------------------------------------------------------------
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host " npm / npx Verification" -ForegroundColor Cyan
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host ""
$ImportantScripts = @(
"$NodePath\npm.ps1",
"$NodePath\npx.ps1"
)
foreach ($file in $ImportantScripts) {
if (Test-Path $file) {
$sig = Get-AuthenticodeSignature $file
Write-Host $file -ForegroundColor Cyan
Write-Host "Status: $($sig.Status)"
if ($sig.Status -eq "Valid") {
Write-Host "OK - Script signature is valid." -ForegroundColor Green
}
else {
Write-Host "WARNING - Script signature is not valid." -ForegroundColor Red
Write-Host $sig.StatusMessage
}
Write-Host ""
}
}
# ------------------------------------------------------------
# 12. Test commands
# ------------------------------------------------------------
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host " Testing Node.js Commands" -ForegroundColor Cyan
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "node --version" -ForegroundColor Yellow
try {
node --version
}
catch {
Write-Host "Node test failed:" -ForegroundColor Red
Write-Host $_.Exception.Message
}
Write-Host ""
Write-Host "npm --version" -ForegroundColor Yellow
try {
npm --version
}
catch {
Write-Host "npm test failed:" -ForegroundColor Red
Write-Host $_.Exception.Message
}
Write-Host ""
Write-Host "npx --version" -ForegroundColor Yellow
try {
npx --version
}
catch {
Write-Host "npx test failed:" -ForegroundColor Red
Write-Host $_.Exception.Message
}
Write-Host ""
Write-Host "============================================================" -ForegroundColor Green
Write-Host " Setup complete" -ForegroundColor Green
Write-Host "============================================================" -ForegroundColor Green
Write-Host ""
Verify That npx.ps1 Is Now Signed
Once the script has completed, close PowerShell and open a new PowerShell window.
Run:
Get-AuthenticodeSignature "C:\Program Files\nodejs\npx.ps1"
You want to see:
Status : Valid
You can check npm.ps1 as well:
Get-AuthenticodeSignature "C:\Program Files\nodejs\npm.ps1"
Again, the important result is:
Status : Valid
Now:
npx --version
and:
npm --version
should work normally.
Finally, I could run my original command:
npx serve "C:\Projects\TypeRider" -l 3000
without PowerShell throwing the PSSecurityException.
Why Not Just Change the Execution Policy?
You’ll find plenty of fixes online recommending something along the lines of:
Set-ExecutionPolicy Unrestricted
or:
Set-ExecutionPolicy Bypass
Yes, that can make the error disappear.
But it also avoids the security control that caused PowerShell to reject the script in the first place.
If your machine has deliberately been configured with:
AllSigned
I’d rather solve the actual signing problem than disable the protection globally just to get npx working.
There’s also an important distinction between execution-policy scopes. On managed or corporate machines, MachinePolicy or UserPolicy may be controlled through Group Policy. In that situation, you shouldn’t attempt to work around your organisation’s policy; speak to whoever manages the machine.
Why Trust the Certificate Twice?
The script adds our self-signed certificate to:
Trusted Root Certification Authorities
and:
Trusted Publishers
These solve slightly different parts of the trust problem.
Because the certificate is self-signed, Windows needs to trust the certificate itself.
PowerShell also needs to recognise the signer as a trusted publisher.
The private key remains in:
Cert:\CurrentUser\My
and is used when we call:
Set-AuthenticodeSignature
to sign the scripts.
Why Sign All the Node.js .ps1 Files?
You could sign only:
npx.ps1
However, if npx.ps1 is causing the problem today, there’s a good chance you’ll encounter exactly the same issue when running:
npm
That’s because Node.js also installs:
npm.ps1
Instead of fixing each PowerShell wrapper as we encounter it, the script finds:
Get-ChildItem -Path "C:\Program Files\nodejs" -Filter "*.ps1"
and signs the Node PowerShell wrappers together.
What Happens When Node.js Is Updated?
There’s one catch with this solution.
An Authenticode signature applies to the contents of a particular file.
If you update or reinstall Node.js, files such as:
npm.ps1
npx.ps1
may be replaced.
Your locally applied signatures will therefore disappear with the old files.
If you suddenly see:
npx.ps1 is not digitally signed
again after upgrading Node.js, don’t immediately assume something has gone wrong with your certificate.
Check:
Get-AuthenticodeSignature "C:\Program Files\nodejs\npx.ps1"
If the Node installer replaced the script, simply run the signing script again.
Because the script first searches for the existing certificate, it won’t unnecessarily create another certificate every time.
Check Which npx PowerShell Is Actually Running
Another useful diagnostic command is:
Get-Command npx -All
This helps determine exactly what PowerShell is resolving when you type:
npx
You can also check:
Get-Command npm -All
This is particularly useful when you have multiple versions of Node.js installed or you’re using a Node version manager.
The Short Version
If you simply need your development server running right now, try:
npx.cmd serve "C:\Projects\TypeRider" -l 3000
If that works, you don’t necessarily need to change anything else.
If you want to continue using:
npx
normally while keeping PowerShell’s stricter AllSigned policy, create a local code-signing certificate, trust it, and sign the Node.js PowerShell wrappers.
The end result is that:
npx serve "C:\Projects\TypeRider" -l 3000
works while your existing PowerShell execution policy remains intact.
Useful Commands
Check execution policies:
Get-ExecutionPolicy -List
Find which npx will execute:
Get-Command npx -All
Check the npx signature:
Get-AuthenticodeSignature "C:\Program Files\nodejs\npx.ps1"
Check the npm signature:
Get-AuthenticodeSignature "C:\Program Files\nodejs\npm.ps1"
Quick workaround:
npx.cmd serve "C:\Projects\TypeRider" -l 3000
