Auditing Windows Optional Features: The Bloat That Widens Your Attack Surface
RSAT, TFTP, SMBv1, and the Windows optional components sitting enabled on your endpoints for no reason - how to inventory them and shut the unneeded ones down.
Every Windows install ships with a menu of optional components — some enabled by default, some switched on years ago by an admin who needed them once. Each one is code on disk, and a surprising number expose network listeners, script interpreters, or legacy protocols. Attack surface reduction usually gets framed as "harden what you run." The cheaper, more durable win is stop running what you don't need at all. This is a walkthrough of how to inventory Windows optional features and disable the ones that only exist to widen your attack surface.
Two different feature stores, and why both matter
Windows tracks add-on components in two overlapping places, and you have to check both:
- Optional Features (Capabilities) — the "Add an optional feature" list. RSAT tools, the OpenSSH client/server, Windows Media Player, Steps Recorder, and similar. Managed with
Get-WindowsCapability. - Windows Features (DISM feature names) — the "Turn Windows features on or off" list. SMB 1.0, the TFTP client, Telnet client, .NET 3.5, WSL, Hyper-V, the legacy PowerShell v2 engine. Managed with
Get-WindowsOptionalFeature.
A machine can look clean in one view while carrying real risk in the other. SMBv1 and the PowerShell 2.0 engine live in the DISM list, not the Capabilities list — miss it and you've audited half the surface.
Inventory first
Before you disable anything, get a complete picture across both stores. On a single machine:
# DISM-style Windows features that are enabled
Get-WindowsOptionalFeature -Online |
Where-Object State -eq 'Enabled' |
Sort-Object FeatureName |
Select-Object FeatureName
# Installed capabilities (RSAT, OpenSSH, legacy media, etc.)
Get-WindowsCapability -Online |
Where-Object State -eq 'Installed' |
Select-Object Name
Export this to a baseline. The goal isn't to nuke everything that's enabled — it's to explain every enabled component. Anything you can't justify is a candidate for removal.
The usual offenders
These are the components that repeatedly turn up enabled with no operational reason:
- SMB 1.0/CIFS (
SMB1Protocol) — deprecated, wormable (WannaCry, NotPetya), and pre-auth vulnerable. If anything still needs it, replace that thing, don't keep SMBv1. - PowerShell 2.0 engine (
MicrosoftWindowsPowerShellV2) — a downgrade target that bypasses AMSI, script block logging, and Constrained Language Mode. Attackers explicitly callpowershell -version 2to blind your telemetry. - TFTP and Telnet clients — living-off-the-land download/exfil binaries with no place on a modern endpoint.
- OpenSSH Server — great when deliberately deployed and firewalled; a quiet inbound listener when someone flipped it on to test something and forgot.
- WSL / Hyper-V / sandboxing features — legitimate for developers, but each adds a virtualization surface and, in WSL's case, a Linux userland your EDR may not inspect. Enable per-role, not fleet-wide.
- RSAT admin tools on ordinary workstations — AD/DNS/GPO management consoles belong on admin jump boxes, not every desk. They hand a foothold rich reconnaissance tooling for free.
Disabling safely
Remove the two highest-value offenders and reboot to confirm nothing you depend on breaks:
# Kill the PowerShell 2.0 downgrade path
Disable-WindowsOptionalFeature -Online `
-FeatureName MicrosoftWindowsPowerShellV2Root -NoRestart
# Remove SMBv1 entirely
Disable-WindowsOptionalFeature -Online `
-FeatureName SMB1Protocol -NoRestart
# Drop a capability you can't justify (example: TFTP)
Get-WindowsCapability -Online |
Where-Object Name -like '*TFTP*' |
Remove-WindowsCapability -Online
Always stage this. Disabling .NET 3.5 or a virtualization feature can break a line-of-business app. The point of the inventory step is to make removal a deliberate, reversible decision — not a blind sweep.
Why this drifts back
The hard part isn't the one-time cleanup — it's that optional features creep back. A developer enables WSL. A troubleshooting session turns on the Telnet client. A reimaged laptop ships with an older default set. Point-in-time hardening decays, and "we disabled SMBv1 last year" is not the same as "SMBv1 is disabled right now, on all 60 machines."
Where WinSentinel fits
On a single machine, WinSentinel is free and unrestricted — all 33 audit modules, no limits. It enumerates both the Capabilities and DISM feature stores, flags risky components like SMBv1, the PowerShell 2.0 engine, TFTP/Telnet clients, and stray inbound listeners, and folds them into your security score with concrete remediation steps. You get the full inventory-and-justify workflow above without hand-writing the queries.
For organizations, WinSentinel Pro adds fleet orchestration on top: a central node that rolls up optional-feature posture across every endpoint, alerts when a machine re-enables a component you'd disabled (drift detection), and maps the findings into compliance rollups so an auditor sees "SMBv1 disabled fleet-wide" rather than a spreadsheet of hopes. The audit itself is the same everywhere — Pro is about seeing and enforcing it across many machines at once.
The takeaway
Optional features are the cheapest attack surface to eliminate because you're not hardening a control — you're removing code that had no reason to run. Inventory both feature stores, justify every enabled component, disable the rest, and then keep watching, because the list will try to grow back. A component that isn't installed can't be exploited, downgraded to, or relayed through.