Code Signing Best Practices
Want to keep your software and code safe?
Enter your contact information below below to receive your FREE Best Practices PDF:
PowerShell is a popular command-line shell and scripting language. It’s versatile, easy to use and learn, and it’s loved by 43.77% of developers surveyed by Stackoverflow. Utilized mainly to automate any kind of repetitive tasks, it’s a powerful ally for busy developers and organizations aiming to save time and resources and increase productivity. PowerShell is a great thing… so long as your PowerShell scripts work.
Discover the meaning behind the ‘PowerShell script is not digitally signed’ error that could block your activities, slow down your operations and, if ignored, put at risk the security of your devices. Find out:
Come and join us in this adventure. Together, we’ll drill down on this common PowerShell error message and explore what you can do to mitigate it. Ready, steady, go!
Did you just download a cool PowerShell script but, when you try to execute it on your Windows device, you can’t get past the ‘PowerShell script is not digitally signed’ error message?
Oops! It looks like you’re trying to run a script that hasn’t been signed by a trusted publisher. As a result, your operating system considers it unsafe, blocks it from running, and shows you the security warning message.
In the most basic sense, the reason you’re getting the “PowerShell Script Is Not Digitally Signed” is because, as the error implies, your code isn’t signed using a code signing certificate. Yes, it’s really that simple. So get a code signing certificate and start signing your PowerShell scripts right now!
The “PowerShell script is not digitally signed” message is the outcome of one of Microsoft’s already built-in security features. The protection is based on the script execution policies regulating which scripts are allowed to run on your computer.
Many organizations change their Windows devices’ execution policies from the default ‘restricted’ (i.e., no scripts can be run on the device) to ‘allsigned.’ Why? Because this specific policy doesn’t cripple your possibility to run legitimate and useful scripts to automate tasks. It prevents executing only those scripts that are considered potentially malicious (i.e., scripts that aren’t signed by a trusted publisher) and could harm your device.
In fact, according to this policy, if the script you’re trying to execute isn’t signed by a trusted publisher (more on that in a minute), it’ll be blocked from running. Thus, it’ll trigger the “PowerShell script is not digitally signed” error message.
But what are exactly these Windows execution policies? What are the differences between them? This is what we’re going to find out next.
Windows execution policies define whether you can load configuration files or run PowerShell scripts. They can be used to set execution policies for a single device or user, a group of users (i.e., group policy), your current session, or even for a particular file/script.
They’re an effective preventive measure that’ll protect you from running dangerous scripts unintentionally. Let’s consider a quick example. Have you ever heard of fileless malware? It’s a sneaky malware that hijacks PowerShell and other Windows built-in tools to carry out attacks. In some cases, like the one discovered in June 2022, it’s enough that a user opens a simple malicious Word document for the attack to succeed.
As this technique doesn’t install any malware on the device, it can easily go undetected by traditional antivirus software and it doesn’t leave any trace on the system. Fear not, though, as some specific Windows execution policies can help you protect your users and devices from these attacks.
How? Let’s have a look at each Windows execution policy and its characteristics to find it out:
|Windows Execution Policy||Policy Features||Level of Protection|
|2. Remote Signed|
|3. All Signed|
OK, we get it. I know that when you have to look for a specific error among your application’s event logs or push an urgent security update to all your organization’s devices, the last thing you need is an error message preventing your PowerShell script from running. And just because it isn’t signed. At first, it may sound like a lot of fuss for nothing; however, there’s a reason behind it — a good one.
PowerShell is a wonderful, powerful tool. It’s one of the fundamental requirements for all Microsoft Administrator certifications: from Microsoft 365 security admin to desktop, and Azure admin. It’s popular among IT professionals and attackers alike. In fact, PowerShell is considered so dangerous that, in June 2022, the cyber intelligence agencies from the U.S., U.K., and New Zealand published a list of security measures to shield PowerShell from cybercriminals.
Their philosophy? PowerShell can be dangerous, but the solution isn’t removing it or disabling it; it’s taking advantage of PowerShell’s features to effectively protect it.
Microsoft knows this.
In such a dangerous environment, leaving its operating system’s configuration management and task automation program (i.e., PowerShell) without defense would have been like leaving the door open to cybercriminals. And this is why organizations should err on the safe side regarding how securely they set their Windows device execution policies.
Want to know which execution policy you have set on your Windows device?
1. Open your Windows PowerShell.
2. Type the command-let (cmdlet) Get-ExecutionPolicy. It’ll show you the actual execution policy set on your device.
3. Use the cmdlet Get-ExecutionPolicy -List to view all of the execution policies related to the current session.
If you’re getting the error message ‘PowerShell script is not digitally signed,’ you will probably see that your device’s (or current user’s) execution policy is set to ‘AllSigned’ or ‘Remote Signed’ (in the case of a Window server machine). If you’re not seeing the error message but can’t run the script, it’s likely because your execution policies are set to ‘Restricted’ or ‘Undefined.’
Important! Order matters. This means that the highest configured item on the list has precedence over the lowest ones.
Now that you know what this security message means and why you or your users are getting it, how can you set it so that this issue won’t happen again? Keep reading to find it out.
There are many ways to overcome this error. Some are better than others, though, above all when talking about security. Let’s explore the different methods available one by one. It’ll enable you to make an informed choice on which one works best for you and your users.
|Solutions to the ‘PowerShell Not Digitally Signed’ Error||Items Needed to Implement It||Level of Security|
|1. Sign Your PowerShell Scripts||
||High. The user will always be able to validate the identity of the publisher and confirm the integrity of the script.|
|2. Change or Bypass the Windows Execution Policy on Your Device, User, Group or Session||
||Low. Users will be able to run everything without PowerShell displaying warning messages.|
|3. Unblock the Downloaded File/Script||
||Very Low. To be used only when you’re 100% sure that the script is safe to run.|
MITRE’s ATT&CK website has a long list of real-world examples of attacks exploiting PowerShell as an attack vector to run malicious executables and commands. From the infamous Cobalt Strike malware to the Revil ransomware family and Emotet, they all used PowerShell to deliver or execute malicious codes.
With the average cost of ransomware attacks reaching $4.54 million in 2022 and IBM expecting a spike in the same type of attacks in 2023, every protection layer you can add to your organization counts. This includes digitally signing your executables to not trigger the ‘PowerShell script is not digitally signed” warning message.
You can do all of this in one fell swoop. Isn’t that marvelous? This is why, like many security professionals, I consider this the best way to fix this PowerShell error.
How can you take advantage of the power of this solution?
That’s it. You’re all set!
Prove Your Software Is Trustworthy
Signing your code shows users that your software and updates can be trusted.
Download our free code signing best practices eBook to learn how to help keep your supply chain secure and your company, customers & end-users safe.
Your boss has asked you to ensure that all workstations on your floor will be shut down by 6 p.m. due to extraordinary maintenance to the building’s electrical system. If done manually, you would have to check more than 100 devices. You’ll never get home on time for dinner and tonight is pizza night!
You pause for a moment, and then you have a flash of genius: use a PowerShell script to automate the shutdown of workstations. Problem solved. A few minutes before 6, you try to run your script and the dreaded ‘PowerShell script is not digitally signed’ message comes up, blocking the whole operation.
After a moment of panic, you remember that the organization’s default execution policy for all Windows machines is set to ‘AllSigned,’ including yours. As the script you wrote isn’t signed, it can’t be executed. And you don’t have a code signing certificate at hand.
You need another solution, fast. What about changing the execution policy on your device? That’s feasible and it takes less than a minute. While this isn’t great from a security perspective, it’s more convenient than spending hours manually switching hundreds of computers off. You check the internet and find out that there are two options:
This is the easiest but also one of the riskiest solutions. It sets the execution policy to ‘Unrestricted’ (i.e., everything can run), and it retains this policy until you decide to change the policy again. This means that if you forget about it, if one day you click on a malicious script by mistake or without knowing it, it’ll be executed. In the best-case scenario, your device will be infected by malware. Worst-case scenario, your organization will be the victim of a cyber attack, ransomware attack or data breach.
Still thinking this solution is the best for you? Your choice. The cmdlet to use is Set-ExecutionPolicy Unrestricted.
You don’t want to risk ending up on the chopping board because your organization has been the victim of a fileless malware attack due to your policy change to unrestricted? Disregard your actual execution policy only for a single PowerShell session.
It’ll allow you to run your script only for one session by ignoring your execution policy settings. The advantage? The bypass lasts just one session leaving the execution policy unchanged. How can you do it?
Open a PowerShell session with the execution policy set to ‘Bypass’ using the cmdlet: Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass.
Now pick the one you prefer and get ready to eat your pizza!
Are you getting the ‘PowerShell script is not digitally signed’ security error when trying to:
If you’re really, really sure that the script is safe even if it isn’t signed, you can unblock it using the Unblock -file cmdlet:
Unblock-File -Path YourPathToTheScript\script-example.ps1.
Use this solution carefully, though, because malware is lurking everywhere, even on trusted code hosting platforms like GitHub. In fact, research published in October 2022 shows that 10.3% of the 47,313 proof of concept (POC) repositories shared on GitHub between 2017 and 2021 were malicious.
So, now that you know the options you have to fix the error ‘PowerShell script is not digitally signed,’ which one are you going to choose? Are you going to opt for the more secure solution, signing all your PowerShell scripts that’ll also enable you to say goodbye to the error message for good or, are you going for the quick and dirty ones that leave users’ devices at risk?
Choose wisely and remember: the shortest path isn’t always the best option.
Do you want to know more about other PowerShell security features? Discover them in just three minutes by reading this interesting Microsoft learning piece.
PowerShell is a wonderful scripting language that enables you to control and automate nearly everything in IT remotely. It enables you to do everything from parsing structured data to automatically managing and installing updates on all your organization’s machines simultaneously. Heck, it even makes creating SQL servers a breeze.
However, a “PowerShell not digitally signed” error could spell disaster for an organization trying to push a critical security update to its whole Windows machine fleet. And, as you’ve learned, changing the Windows execution policy or asking your users to unblock the downloaded file aren’t the best solutions because they leave users’ devices insecure.
This is why it’s better to sign all your PowerShell scripts before implementing them. Doing this will help you kill two birds with one stone as it’ll
So, from now on, no more asking your users to change policies. Sign your scripts!