Unsigned drivers are often the culprits behind system instability, compatibility issues, and—more alarmingly—security vulnerabilities. For IT professionals, especially those managing endpoints across distributed environments, proactively identifying and managing unsigned drivers is not just good practice—it’s essential. Leveraging PowerShell, a cornerstone automation tool for IT and MSPs, is one of the most efficient ways to accomplish this. This post examines how to detect Unsigned Drivers with PowerShell, complete with NinjaOne integration for reporting and documentation.
Background
Driver signatures are digital certificates that verify the authenticity and integrity of a driver. When a driver is unsigned, it lacks this verification, opening the door to a myriad of issues. Malicious actors often exploit unsigned drivers to embed rootkits or bypass system-level protections. As a result, endpoint hygiene checks increasingly focus on identifying such drivers.
For Managed Service Providers (MSPs) and IT administrators managing large fleets of Windows devices, a PowerShell script to get Unsigned Driver Alerts offers a scalable, repeatable, and non-intrusive solution. By integrating the output into a custom field within NinjaOne, IT teams can track, document, and act on these vulnerabilities directly within their RMM platform.
The Script
<# .SYNOPSIS Get a list of unsigned drivers on the system. .DESCRIPTION Get a list of unsigned drivers on the system. By using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https://www.ninjaone.com/terms-of-use. Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms. Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party. Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider. Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations. Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks. Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script. EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA). .EXAMPLE (No Parameters) [Info] Unsigned Drivers Found Device Name INF Name Is Signed Manufacturer ----------- -------- --------- ------------ Local Print Queue printqueue.inf False Microsoft Microsoft Print to PDF mspdf.inf False Microsoft Microsoft XPS Document msxpsdrv.inf False Microsoft .OUTPUTS None .NOTES Minimum OS Architecture Supported: Windows 10, Windows Server 2016 Release Notes: Initial Release #> [CmdletBinding()] param ( [Parameter()] [String]$WYSIWYGCustomField ) begin { # If using script form variables, replace command line parameters with the form variables. if ($env:wysiwygCustomFieldName -and $env:wysiwygCustomFieldName -notlike "null") { $WYSIWYGCustomField = $env:wysiwygCustomFieldName } function Set-NinjaProperty { [CmdletBinding()] Param( [Parameter(Mandatory = $True)] [String]$Name, [Parameter()] [String]$Type, [Parameter(Mandatory = $True, ValueFromPipeline = $True)] $Value, [Parameter()] [String]$DocumentName ) # Measure the number of characters in the provided value $Characters = $Value | Out-String | Measure-Object -Character | Select-Object -ExpandProperty Characters # Throw an error if the value exceeds the character limit of 200,000 characters if ($Characters -ge 200000) { throw "Character limit exceeded: the value is greater than or equal to 200,000 characters." } # Initialize a hashtable for additional documentation parameters $DocumentationParams = @{} # If a document name is provided, add it to the documentation parameters if ($DocumentName) { $DocumentationParams["DocumentName"] = $DocumentName } # Define a list of valid field types $ValidFields = "Attachment", "Checkbox", "Date", "Date or Date Time", "Decimal", "Dropdown", "Email", "Integer", "IP Address", "MultiLine", "MultiSelect", "Phone", "Secure", "Text", "Time", "URL", "WYSIWYG" # Warn the user if the provided type is not valid if ($Type -and $ValidFields -notcontains $Type) { Write-Warning "$Type is an invalid type. Please check here for valid types: https://ninjarmm.zendesk.com/hc/en-us/articles/16973443979789-Command-Line-Interface-CLI-Supported-Fields-and-Functionality" } # Define types that require options to be retrieved $NeedsOptions = "Dropdown" # If the property is being set in a document or field and the type needs options, retrieve them if ($DocumentName) { if ($NeedsOptions -contains $Type) { $NinjaPropertyOptions = Ninja-Property-Docs-Options -AttributeName $Name @DocumentationParams 2>&1 } } else { if ($NeedsOptions -contains $Type) { $NinjaPropertyOptions = Ninja-Property-Options -Name $Name 2>&1 } } # Throw an error if there was an issue retrieving the property options if ($NinjaPropertyOptions.Exception) { throw $NinjaPropertyOptions } # Process the property value based on its type switch ($Type) { "Checkbox" { # Convert the value to a boolean for Checkbox type $NinjaValue = [System.Convert]::ToBoolean($Value) } "Date or Date Time" { # Convert the value to a Unix timestamp for Date or Date Time type $Date = (Get-Date $Value).ToUniversalTime() $TimeSpan = New-TimeSpan (Get-Date "1970-01-01 00:00:00") $Date $NinjaValue = $TimeSpan.TotalSeconds } "Dropdown" { # Convert the dropdown value to its corresponding GUID $Options = $NinjaPropertyOptions -replace '=', ',' | ConvertFrom-Csv -Header "GUID", "Name" $Selection = $Options | Where-Object { $_.Name -eq $Value } | Select-Object -ExpandProperty GUID # Throw an error if the value is not present in the dropdown options if (!($Selection)) { throw [System.ArgumentOutOfRangeException]::New("Value is not present in dropdown options.") } $NinjaValue = $Selection } default { # For other types, use the value as is $NinjaValue = $Value } } # Set the property value in the document if a document name is provided if ($DocumentName) { $CustomField = Ninja-Property-Docs-Set -AttributeName $Name -AttributeValue $NinjaValue @DocumentationParams 2>&1 } else { # Otherwise, set the standard property value $CustomField = $NinjaValue | Ninja-Property-Set-Piped -Name $Name 2>&1 } # Throw an error if setting the property failed if ($CustomField.Exception) { throw $CustomField } } } process { # Get the list of unsigned drivers $UnsignedDrivers = driverquery.exe /si /FO CSV | ConvertFrom-Csv | Select-Object @{ label = "Device Name"; expression = { $_.DeviceName } }, @{ label = "INF Name"; expression = { $_.InfName } }, @{ label = "Is Signed"; expression = { if ($_.IsSigned -eq "TRUE") { $true }else { $false } } }, Manufacturer | Where-Object { -Not $_."Is Signed" } # Create Html Table $HtmlTable = [System.Collections.Generic.List[String]]::new() # Add header $HtmlTable.Add("<h2>Unsigned Drivers</h2>") # Output the list of unsigned drivers to the table if ($UnsignedDrivers) { Write-Host "[Info] Unsigned Drivers Found" # Add table of unsigned drivers $HtmlTable.Add($($UnsignedDrivers | ConvertTo-Html -Fragment | Out-String)) # Output the list of unsigned drivers $UnsignedDrivers | Format-Table -AutoSize | Out-String -Width 4000 | Write-Host } else { Write-Host "[Info] No Unsigned Drivers Found" $HtmlTable.Add("<p>No unsigned drivers found.</p>") } # If a custom field name is provided, set the custom field with the list of unsigned drivers if ($WYSIWYGCustomField) { try { Write-Host "[Info] Attempting to set Custom Field '$WYSIWYGCustomField'." Set-NinjaProperty -Name $WYSIWYGCustomField -Value $($HtmlTable -join [System.Environment]::NewLine | Out-String) Write-Host "[Info] Successfully set Custom Field '$WYSIWYGCustomField'!" } catch { Write-Host "[Warn] Failed to set Custom Field '$WYSIWYGCustomField'." } } } end { }
Detailed Breakdown
This script is structured in PowerShell using advanced functions and built-in error handling, and it does more than just display unsigned drivers—it makes them actionable within NinjaOne.
Step-by-Step Workflow
- Parameter Setup and Environment Variable Integration
- The script optionally accepts a $WYSIWYGCustomField parameter, or retrieves it from an environment variable. This enables automated workflows through NinjaOne forms or UI variables.
- Function Definition – Set-NinjaProperty
- This function handles setting NinjaOne custom fields. It includes:
- Validation for field types.
- Conversion logic for various field data types (checkboxes, dates, dropdowns).
- Error handling for character limits (200,000 chars).
- API calls to Ninja-Property-Set-Piped or Ninja-Property-Docs-Set.
- This function handles setting NinjaOne custom fields. It includes:
- Main Logic – Retrieving Unsigned Drivers
- Executes driverquery.exe /si /FO CSV to retrieve driver data.
- Parses the output to extract relevant fields: Device Name, INF Name, Signature Status, and Manufacturer.
- Filters out signed drivers, showing only those marked as unsigned.
- HTML Table Construction
- Generates an HTML fragment listing all unsigned drivers.
- This is stored in a list that can be injected into NinjaOne’s custom fields for detailed visibility.
- Reporting to NinjaOne
- If a WYSIWYG custom field is specified, the HTML report is uploaded via Set-NinjaProperty.
Potential Use Cases
Case Study: Endpoint Vulnerability Audit in a School District
An IT admin managing over 300 endpoints across multiple campuses initiates a routine compliance audit. Using this script within a NinjaOne automation policy, they identify several devices running unsigned print drivers from third-party manufacturers. The HTML output appears directly in the custom field on each device record. This facilitates:
- Immediate risk classification
- Ticket generation
- Scripted remediation or driver updates
Comparisons
Other Methods:
- Manual Inspection via Device Manager: Time-consuming and not scalable.
- Third-party tools (e.g., Driver Verifier or SIEM agents): Powerful but may be overkill for simple unsigned driver checks and lack direct RMM integration.
This Script:
- Lightweight
- Transparent
- Fully automatable within RMM workflows
- Produces actionable output
FAQs
Q: Can this script run silently as part of an automated job?
A: Yes. It supports silent execution and can be triggered as part of routine checks or post-patching workflows.
Q: What happens if the output exceeds the character limit?
A: The script enforces a 200,000-character limit. If exceeded, it throws a descriptive error and avoids corrupting the field data.
Q: Does it detect unsigned kernel-mode drivers?
A: It lists all unsigned drivers via driverquery.exe, including kernel-mode ones if applicable.
Implications
Running unsigned drivers can expose systems to critical security vulnerabilities. By automating the detection and reporting of these drivers, IT professionals ensure higher levels of endpoint security and compliance. Left unchecked, unsigned drivers could allow rootkits to operate undetected or lead to privilege escalation exploits.
This script promotes proactive threat discovery, a key pillar of modern endpoint defense strategy.
Recommendations
- Run Regularly: Schedule this script on a monthly or quarterly basis.
- Pair with Alerts: Use NinjaOne alerting to notify when new unsigned drivers are detected.
- Audit Routinely: Integrate with patch management and vulnerability scanning.
- Customize Fields: Tailor the WYSIWYG field to appear prominently in device details for quick triage.
Final Thoughts
Identifying unsigned drivers is a non-negotiable aspect of IT risk management. This Unsigned Driver Alert PowerShell script, when paired with NinjaOne’s automation and documentation capabilities, offers a streamlined, scalable solution. MSPs and IT teams gain a powerful tool for visibility, compliance, and remediation—ensuring that their endpoints remain not only functional but secure.
By embedding such insights directly into NinjaOne custom fields, teams gain context-rich data for smarter decisions and faster incident response. In short, it’s automation that pays security dividends.