I've got about 100 servers that I have to make sure are mitigated for Spectre and Meltdown. The good news is that Microsoft has created a handy-dandy PowerShell commandlet that will check the mitigation status of any Windows computer. The bad news is they did not include any custom parameters for it, it only has the common paramters.

The real bad news is that the output is very verbose and not really filterable in a real way. Here's an example of the output of get-speculationcontrolsettings from just one server:

Speculation control settings for CVE-2017-5715 [branch target injection]

Hardware support for branch target injection mitigation is present: False
Windows OS support for branch target injection mitigation is present: True
Windows OS support for branch target injection mitigation is enabled: False
Windows OS support for branch target injection mitigation is disabled by system policy: True
Windows OS support for branch target injection mitigation is disabled by absence of hardware support: True

Speculation control settings for CVE-2017-5754 [rogue data cache load]

Hardware requires kernel VA shadowing: True
Windows OS support for kernel VA shadow is present: True
Windows OS support for kernel VA shadow is enabled: False

Suggested actions

 * Install BIOS/firmware update provided by your device OEM that enables hardware support for the branch target injection mitigation.
 * Follow the guidance for enabling Windows Server support for speculation control mitigations described in https://support.microsoft.com/help/4072698

What I would really like to do is have a nice table that I can export to CSV that just shows server names in one column and True/False values in other columns.

What does help a little is that I can pipe the output to select and it will create a single table row at the end of all that output junk above, but when I run get-speculationcontrolsettings against a whole array of servers, it puts out a copy of all that junk and then the table row for one server, then outputs the junk again and the table row for the next server, etc.

I could send everything to a text file, then search & replace to get rid of all the junk, and then convert text to table and then copy paste to Excel.

But what would be really cool is if there is some way in PowerShell to... well I don't know. Only output table data? Maybe populate an array somehow and then echo the array?

Any bright ideas?

Edit - Note for others

The final version of the command I'm using (after commenting out all of the write-host statements in the module itself as suggested in the accepted answer) looks like this:

Invoke-Command -ComputerName $servernamess ${function:Get-SpeculationControlSettings} -ErrorAction SilentlyContinue | select PSComputerName, BTIHardwarePresent, BTIWindowsSupportPresent, BTIDisabledBySystemPolicy, BTIDisabledByNoHardwareSupport, KVAShadowWindowsSupportPresent, KVAShadowWindowsSupportEnabled | ft

If you populate the $servernames variable with a list of computer names, however you want to do that, then what this command does is remotely executes the get-speculationcontrolsettings command on all the servers so named. You won't see the verbose output if you've edited the psm1 file. Also, if you have any computer names in the variable for computers that are not accessible, you'll get errors on those, so that's why the -ErrorAction SilentlyContinue parameter is in there. Finally, the command selects the name of the server and the important findings regarding the mitigations, and formats them in a table.

Some quick find and replace to turn whitespace into commas and you've got a CSV that you can open in Excel and apply some conditional formatting for management to see where you are on Spectre and Meltdown in your Windows environment, without waiting for compliance to do another Nessus scan.


If you know PowerShell a bit you can also make a copy of the file:

C:\Program Files\WindowsPowerShell\Modules\SpeculationControl\1.0.x\SpeculationControl.psm1

change the output into something you like and then run the new script.

  • Good idea! Also I could see how they created the "junk" output and figure out what they did to keep it from being written to the transcript. Jan 20 '18 at 14:36
  • This was easy. All I had to do was comment out all of the write-host statements. Which makes sense because write-host output does not get logged in a session transcript. Jan 20 '18 at 17:50

I decided to try doing it the hard way and I stumbled on the answer.

By running these commands:

$servers = Get-ADComputer -Filter *
$servernames = $servers.name
Start-Transcript -Path "C:\SpecControlStatus.txt"
Invoke-Command -ComputerName $servernames ${function:Get-SpeculationControlSettings} | select PSComputerName, KVAShadowWindowsSupportPresent

The transcript does not have all the "junk" output from each invocation of Get-SpeculationControlSettings, it only has the table created by the select statement.

I guess the "junk" output is somehow console only.

Note that the Windows Domain I am working on only has application servers in it, so getting the names of all the computers in the domain is also the names of all the servers I need to mitigate.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.