Bird
Raised Fist0
PowerShellscripting~15 mins

Code signing in PowerShell - Deep Dive

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Overview - Code signing
What is it?
Code signing is a way to add a digital signature to scripts or software. This signature proves the code comes from a trusted source and has not been changed. It uses special certificates to create this proof. When you run signed code, your system can check if it is safe.
Why it matters
Without code signing, anyone could change or fake scripts, causing security risks like viruses or data theft. Code signing helps users trust the code they run and protects developers' work from tampering. It makes software safer and helps prevent harmful attacks.
Where it fits
Before learning code signing, you should understand basic scripting and certificates. After this, you can learn about secure script execution policies and advanced certificate management. Code signing fits into the security part of scripting and automation.
Mental Model
Core Idea
Code signing is like sealing a letter with a unique wax stamp that proves who sent it and that it wasn’t opened or changed.
Think of it like...
Imagine sending a letter sealed with a special wax stamp only you have. The receiver checks the stamp to be sure the letter is really from you and hasn’t been opened or altered. Code signing works the same way for scripts and software.
┌───────────────┐       ┌───────────────┐       ┌───────────────┐
│  Developer's  │  signs│  Script/Code  │  sends│  User/System  │
│  Private Key  │──────▶│  with Digital │──────▶│  Verifies     │
│               │       │  Signature    │       │  Signature    │
└───────────────┘       └───────────────┘       └───────────────┘
Build-Up - 7 Steps
1
FoundationWhat is code signing
🤔
Concept: Introduction to the basic idea of code signing and digital signatures.
Code signing means adding a special digital signature to your script or program. This signature is created using a secret key only the developer has. It proves the code is authentic and unchanged. Think of it as a digital seal of approval.
Result
You understand that code signing adds proof of origin and integrity to code.
Understanding that code signing is about trust and protection helps you see why it is important for safe scripting.
2
FoundationHow certificates work
🤔
Concept: Basics of certificates and keys used in code signing.
Certificates are digital ID cards issued by trusted authorities. They contain a public key and information about the owner. The developer uses a private key to sign code, and others use the public key in the certificate to verify it. Certificates link identity to keys.
Result
You know that certificates connect a developer’s identity to their signing key.
Knowing certificates are like digital ID cards clarifies how systems trust signed code.
3
IntermediateSigning scripts with PowerShell
🤔Before reading on: do you think signing a script changes its content or just adds a signature? Commit to your answer.
Concept: How to use PowerShell commands to sign scripts with a certificate.
In PowerShell, you use the Set-AuthenticodeSignature command to sign a script file. You need a code signing certificate installed on your system. The command adds a signature block to the script without changing its code. Example: $cert = Get-ChildItem -Path Cert:\CurrentUser\My | Where-Object { $_.Subject -like '*YourName*' } Set-AuthenticodeSignature -FilePath .\script.ps1 -Certificate $cert
Result
The script file now contains a digital signature that can be verified before running.
Understanding that signing adds a signature block without altering code helps avoid confusion about script integrity.
4
IntermediateVerifying signed scripts
🤔Before reading on: do you think verification checks the code content or just the signature? Commit to your answer.
Concept: How PowerShell checks if a script’s signature is valid and trusted.
PowerShell uses Get-AuthenticodeSignature to check a script’s signature. It reports if the signature is valid, invalid, or missing. It also checks if the certificate is trusted and not expired. Example: Get-AuthenticodeSignature -FilePath .\script.ps1 This helps decide if the script is safe to run.
Result
You can confirm if a script is signed and if the signature is trustworthy.
Knowing verification checks both signature and certificate trust prevents running unsafe scripts.
5
IntermediateExecution policies and signing
🤔Before reading on: do you think PowerShell always runs unsigned scripts? Commit to your answer.
Concept: How PowerShell’s execution policies use code signing to control script running.
PowerShell has execution policies like Restricted, RemoteSigned, and AllSigned. For example, RemoteSigned requires scripts from the internet to be signed. AllSigned requires all scripts to be signed. This policy helps prevent running untrusted code. You can check policy with Get-ExecutionPolicy.
Result
You understand how signing interacts with system settings to protect script execution.
Understanding execution policies shows how code signing fits into overall script security.
6
AdvancedCreating your own code signing certificate
🤔Before reading on: do you think you must buy a certificate to sign code? Commit to your answer.
Concept: How to create a self-signed code signing certificate for testing or internal use.
You can create a self-signed certificate using PowerShell’s New-SelfSignedCertificate command. This is useful for testing or internal scripts. Example: New-SelfSignedCertificate -Type CodeSigning -Subject 'CN=MyTestCert' -CertStoreLocation Cert:\CurrentUser\My Note: Self-signed certificates are not trusted by others by default.
Result
You can sign scripts without buying a certificate, but trust is limited.
Knowing how to create self-signed certificates empowers testing and internal automation.
7
ExpertHandling certificate trust and revocation
🤔Before reading on: do you think a valid signature always means safe code? Commit to your answer.
Concept: Understanding how trust chains and certificate revocation affect code signing security.
A signature is only as trusted as the certificate chain. Certificates link to trusted root authorities. If a certificate is revoked (e.g., compromised), the signature should be rejected. PowerShell checks revocation lists and trust chains during verification. Managing this is critical in production environments.
Result
You grasp that code signing security depends on certificate trust and revocation status, not just signature presence.
Understanding trust chains and revocation prevents false security assumptions and protects against compromised certificates.
Under the Hood
Code signing uses asymmetric cryptography. The developer’s private key creates a unique digital signature from the script’s content. This signature is attached to the script. When verifying, the system uses the public key from the certificate to decrypt the signature and compare it to the script’s current content hash. If they match, the code is unchanged and from the signer.
Why designed this way?
Asymmetric cryptography allows anyone to verify a signature without exposing the private key, ensuring security. Certificates issued by trusted authorities link keys to real identities, building trust. This design balances security, trust, and usability better than symmetric methods or no signing.
┌───────────────┐       ┌───────────────┐       ┌───────────────┐
│  Script File  │──────▶│  Hash Created │──────▶│  Private Key  │
│  Content      │       │  (Digest)     │       │  Signs Hash   │
└───────────────┘       └───────────────┘       └───────────────┘
        │                                         │
        │                                         ▼
        │                               ┌───────────────────┐
        │                               │  Digital Signature │
        │                               └───────────────────┘
        │                                         │
        ▼                                         ▼
┌───────────────────┐                   ┌───────────────────┐
│ Signed Script     │◀──────────────────│  Verification     │
│ (Script + Sig)    │                   │  Public Key       │
└───────────────────┘                   └───────────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Does a valid signature guarantee the code is safe? Commit to yes or no.
Common Belief:If a script has a valid signature, it must be safe to run.
Tap to reveal reality
Reality:A valid signature only proves the code is from the signer and unchanged, not that it is safe or free from bugs or malicious intent.
Why it matters:Blindly trusting signatures can lead to running harmful code from trusted but compromised or careless developers.
Quick: Can you sign a script without a certificate? Commit to yes or no.
Common Belief:You can sign scripts without any certificate or special keys.
Tap to reveal reality
Reality:Code signing requires a certificate with a private key; without it, you cannot create a valid digital signature.
Why it matters:Trying to sign without a certificate wastes time and causes errors.
Quick: Does signing a script change its behavior? Commit to yes or no.
Common Belief:Signing a script changes how the script runs or its code.
Tap to reveal reality
Reality:Signing only adds a signature block; the script’s code and behavior remain unchanged.
Why it matters:Misunderstanding this can cause confusion about script errors or behavior after signing.
Quick: Is a self-signed certificate trusted by default? Commit to yes or no.
Common Belief:Self-signed certificates are trusted the same as certificates from authorities.
Tap to reveal reality
Reality:Self-signed certificates are not trusted by default and require manual trust configuration.
Why it matters:Assuming trust causes scripts to fail verification or users to ignore warnings.
Expert Zone
1
Code signing timestamps can prove when code was signed, allowing signatures to remain valid even after certificate expiration.
2
Multiple signatures can be added to a single script to represent different signers or stages of approval.
3
Certificate revocation checking can be bypassed in some environments, which may weaken security if not managed properly.
When NOT to use
Code signing is not suitable for scripts that change frequently or are for quick testing; in such cases, using execution policies or sandboxing is better. Also, for internal automation without external distribution, simpler trust models may suffice.
Production Patterns
In production, code signing is combined with strict execution policies, automated certificate management, and continuous integration pipelines that sign code automatically before deployment.
Connections
Public Key Infrastructure (PKI)
Code signing builds on PKI concepts of certificates and asymmetric keys.
Understanding PKI helps grasp how trust chains and certificate authorities support code signing security.
Software Supply Chain Security
Code signing is a key part of securing the software supply chain by verifying code origin and integrity.
Knowing code signing’s role in supply chain security helps prevent attacks like tampering or injecting malicious code.
Legal Document Signing
Both use digital signatures to prove authenticity and prevent tampering.
Recognizing the similarity to legal document signing clarifies why digital signatures are trusted and legally binding.
Common Pitfalls
#1Trying to run unsigned scripts when execution policy requires signed scripts.
Wrong approach:Set-ExecutionPolicy RemoteSigned .script.ps1 # script is unsigned, so blocked
Correct approach:Set-ExecutionPolicy RemoteSigned Set-AuthenticodeSignature -FilePath .\script.ps1 -Certificate $cert .script.ps1 # script runs because it is signed
Root cause:Not understanding how execution policies enforce signature requirements causes script blocking.
#2Using an expired or revoked certificate to sign code.
Wrong approach:Set-AuthenticodeSignature -FilePath .\script.ps1 -Certificate $expiredCert
Correct approach:Use a valid, current certificate: Set-AuthenticodeSignature -FilePath .\script.ps1 -Certificate $validCert
Root cause:Ignoring certificate validity periods or revocation status leads to invalid signatures.
#3Assuming self-signed certificates are trusted by others without configuration.
Wrong approach:New-SelfSignedCertificate -Type CodeSigning -Subject 'CN=Test' Set-AuthenticodeSignature -FilePath .\script.ps1 -Certificate $selfSignedCert # Others try to run script but get trust errors
Correct approach:Distribute and install the self-signed certificate in trusted stores on target machines before running signed scripts.
Root cause:Not realizing trust must be manually established for self-signed certificates.
Key Takeaways
Code signing adds a digital signature to scripts to prove who created them and that they haven’t been changed.
It relies on certificates and asymmetric cryptography to create and verify signatures securely.
PowerShell provides commands to sign and verify scripts, integrating with execution policies for security.
A valid signature does not guarantee safety; trust depends on certificate validity and revocation checks.
Understanding certificate trust and management is essential for effective and secure code signing in production.

Practice

(1/5)
1. What is the main purpose of code signing a PowerShell script?
easy
A. To prove the script is from a trusted source and has not been altered
B. To make the script run faster
C. To encrypt the script content
D. To convert the script into an executable file

Solution

  1. Step 1: Understand code signing purpose

    Code signing is used to verify the identity of the script author and ensure the script has not been changed.
  2. Step 2: Compare options

    Only To prove the script is from a trusted source and has not been altered describes this purpose correctly. Other options describe unrelated actions like encryption or performance.
  3. Final Answer:

    To prove the script is from a trusted source and has not been altered -> Option A
  4. Quick Check:

    Code signing = prove trust and integrity [OK]
Hint: Code signing proves trust and no changes [OK]
Common Mistakes:
  • Thinking code signing encrypts the script
  • Believing code signing speeds up execution
  • Confusing code signing with file conversion
2. Which PowerShell command is used to sign a script with a certificate?
easy
A. New-ScriptSignature
B. Sign-ScriptCertificate
C. Set-AuthenticodeSignature
D. Add-ScriptCertificate

Solution

  1. Step 1: Identify the correct cmdlet for signing

    The official PowerShell cmdlet to sign scripts is Set-AuthenticodeSignature.
  2. Step 2: Verify other options

    Other options are not valid PowerShell commands for signing scripts.
  3. Final Answer:

    Set-AuthenticodeSignature -> Option C
  4. Quick Check:

    Sign script cmdlet = Set-AuthenticodeSignature [OK]
Hint: Remember: Set-AuthenticodeSignature signs scripts [OK]
Common Mistakes:
  • Using non-existent cmdlets like Sign-ScriptCertificate
  • Confusing signing with creating certificates
  • Misspelling the cmdlet name
3. What will be the output of this PowerShell command if the script is successfully signed?
Set-AuthenticodeSignature -FilePath 'script.ps1' -Certificate $cert
medium
A. The script file is deleted
B. An error message about missing parameters
C. No output is shown
D. A Signature object showing Status as Valid

Solution

  1. Step 1: Understand Set-AuthenticodeSignature output

    This cmdlet returns a Signature object with a Status property indicating if signing succeeded.
  2. Step 2: Interpret successful signing output

    If signing succeeds, Status will be 'Valid'. No deletion or silent output occurs.
  3. Final Answer:

    A Signature object showing Status as Valid -> Option D
  4. Quick Check:

    Successful signing = Status Valid output [OK]
Hint: Successful signing returns Status Valid object [OK]
Common Mistakes:
  • Expecting no output after signing
  • Thinking the script file is deleted
  • Confusing error messages with success
4. You run this command but get an error: Set-AuthenticodeSignature : Cannot find the certificate. What is the likely cause?
medium
A. The script is already signed
B. The certificate variable is empty or invalid
C. PowerShell version is too old
D. The script file path is incorrect

Solution

  1. Step 1: Analyze the error message

    The error says it cannot find the certificate, meaning the $cert variable is likely empty or invalid.
  2. Step 2: Check other options

    Incorrect file path causes a different error. PowerShell version or existing signature do not cause this specific error.
  3. Final Answer:

    The certificate variable is empty or invalid -> Option B
  4. Quick Check:

    Certificate missing error = invalid $cert [OK]
Hint: Check certificate variable if 'Cannot find certificate' error [OK]
Common Mistakes:
  • Assuming file path is the problem
  • Thinking PowerShell version causes this error
  • Believing script already signed causes this error
5. You want to sign multiple scripts in a folder using the same certificate. Which PowerShell snippet correctly signs all .ps1 files?
hard
A. Get-ChildItem -Path . -Filter '*.ps1' | ForEach-Object { Set-AuthenticodeSignature -FilePath $_.FullName -Certificate $cert }
B. Set-AuthenticodeSignature -FilePath '*.ps1' -Certificate $cert
C. ForEach ($file in '*.ps1') { Set-AuthenticodeSignature -FilePath $file -Certificate $cert }
D. Get-Content '*.ps1' | Set-AuthenticodeSignature -Certificate $cert

Solution

  1. Step 1: Identify correct way to get all .ps1 files

    Get-ChildItem -Filter '*.ps1' lists all script files in the folder.
  2. Step 2: Apply signing to each file

    Using ForEach-Object to call Set-AuthenticodeSignature on each file with the certificate is correct.
  3. Step 3: Check other options

    Set-AuthenticodeSignature -FilePath '*.ps1' -Certificate $cert tries to sign a wildcard path directly (invalid). ForEach ($file in '*.ps1') { Set-AuthenticodeSignature -FilePath $file -Certificate $cert } treats '*.ps1' as a string list (wrong). Get-Content '*.ps1' | Set-AuthenticodeSignature -Certificate $cert pipes file content, not file paths (wrong).
  4. Final Answer:

    Get-ChildItem -Path . -Filter '*.ps1' | ForEach-Object { Set-AuthenticodeSignature -FilePath $_.FullName -Certificate $cert } -> Option A
  5. Quick Check:

    Use Get-ChildItem + ForEach-Object to sign all scripts [OK]
Hint: Use Get-ChildItem and ForEach-Object to sign multiple files [OK]
Common Mistakes:
  • Trying to sign wildcard paths directly
  • Using file content instead of file paths
  • Treating '*.ps1' as a list of files