03 · Automation
Automating Windows Security Remediation Using PowerShell
The scripts were the easy part. Making them safe to run on real machines was the difficult lesson.
In this article
- The first fixes were not glamorous
- The .NET uninstall problem
- When a small fix kept coming back
- What Intune taught me about delivery
- The problem with one-off fixes
- Separate detection from modification
- Inventory and preflight checks
- Build a safe remediation function
- Keep rollback separate and testable
- Operational controls in Intune
- Engineering review checklist
Patterns for safe detection, controlled changes and reliable post-change evidence.
These are notes from problems I have actually wrestled with in vulnerability operations, not a claim that every feature is solved or that every customer has the same environment. I built VulnOps because the everyday work between finding a vulnerability and closing it deserved better tools.
The first fixes were not glamorous
Some of the first things I automated were SMB signing settings, NTLMv1 hardening, WinVerifyTrust certificate-padding mitigations and .NET findings. Nobody builds a vulnerability platform because editing a registry value sounds thrilling. The point was that these changes recur across many machines and demand consistent evidence. A successful script on my test device was not enough. I had to consider architecture, policy precedence, remote execution, errors and what a separate scanner would report after the change.
The .NET uninstall problem
End-of-life .NET runtimes were particularly exhausting. Sometimes the vulnerable version could only be addressed with the appropriate uninstaller, not by running a newer installer and hoping the old runtime disappeared. We had to get installers or uninstallers onto endpoints, run them carefully and then verify what was actually present. Some applications were dependent on older runtimes, so automatic removal could have broken production. That experience shaped my insistence that a remediation needs a precheck and a postcheck, with an explicit stop when prerequisites or safe assumptions fail.
When a small fix kept coming back
I also dealt with registry mitigations such as Intel BHI settings and recurring application clutter such as classic Teams. In one environment the device build kept including classic Teams even though the current work version was installed. While the master image was being corrected, remediation scripts had to keep clearing the unwanted version on replacement machines. It felt absurd to remediate the same problem repeatedly, but that was also a valuable lesson: some vulnerabilities are symptoms of an image or provisioning problem. Scripting the cleanup helps; removing the source of reintroduction is better.
What Intune taught me about delivery
My experience with Azure administration, Microsoft security tooling, PowerShell and Graph influenced how I thought about deployment. A good script has to fit the mechanism that runs it, especially when using Intune Remediations, where detection exit codes and execution identity matter. The generated artifact is not automatically ready for every tenant. It has to be reviewed against the client environment, tested on a narrow pilot and rolled out under change control. I wanted automation to make the careful path easier, not make the reckless path a single click.
The problem with one-off fixes
Windows vulnerability remediation often looks deceptively simple. Set one registry value, remove one outdated component or launch one silent installer. In a mixed fleet, that simplicity disappears. A script may encounter 32-bit and 64-bit registry views, locked files, pending reboots, partial previous installations, offline endpoints or a policy that resets the setting a few minutes later. I use PowerShell because it exposes local state and supports automation, but the goal is not merely to run commands remotely. The goal is to build a predictable remediation unit that can detect, change, verify and report its result without pretending every machine is identical. Within VulnOps this becomes a reusable three-script pattern suited to Intune Remediations, subject to environment-specific testing and approval.
Separate detection from modification
A detection script should read state and exit with a meaningful result. It should not quietly remediate as a side effect. For example, for a registry mitigation, detection can inspect both native and WOW6432Node paths where applicable, check the value type and compare it with the approved target. In an Intune Remediations workflow, exit code 0 generally indicates compliant status and exit code 1 indicates an issue that calls for remediation. Other execution platforms may use different conventions, so the script contract needs to be written down. Detection should not assume that a successful Get-ItemProperty call means a value is correct. Test the exact value and type, and distinguish unavailable telemetry from confirmed compliance. A failed remote connection is an unknown state, not a healthy computer.
Inventory and preflight checks
Before changing a machine, verify the operating-system version, relevant component presence, administrative context and available disk space. An application update also needs a package-version check so it does not downgrade a newer build. If a service will restart, determine whether that service supports a business-critical application. For installers, preserve expected return codes and interpret a restart-required result separately from outright failure. Avoid broad process termination simply to make an installer succeed. In production, I prefer changes with explicit preconditions and clear skip messages to scripts that force their way past an unexpected state. An automated update on an endpoint should not accidentally become an unplanned reboot of a line-of-business server.
Build a safe remediation function
A useful implementation separates logging, backup, execution and verification. Logging records a timestamp, action, outcome and error context without writing secrets. Backup captures the prior registry state or configuration file before any change. The remediation block uses try/catch with terminating errors where appropriate, but it must also inspect native process exit codes because not every failing executable throws a PowerShell exception. After the change, run the same logical checks used by detection. Do not report success merely because Set-ItemProperty returned. If verification fails, leave a clear failure result for the orchestration platform. Scripts should be idempotent: running them twice against a compliant endpoint should not create duplicate files, reinstall packages unnecessarily or erase the first useful backup.
Keep rollback separate and testable
Registry rollback is not always equivalent to setting a value to zero. If a key did not exist before remediation, restoring the old state may require deleting the new value. If it existed with a particular type, the type matters. For software replacement, rollback can be considerably harder because the prior installer may be unavailable or a database migration may be irreversible. The rollback script therefore needs explicit limitations rather than a promise that every update is undoable. Testing should cover a healthy machine, a vulnerable machine, a partially patched machine and a failed installation. That small matrix catches surprisingly many assumptions before a wider rollout. Where rollback cannot be guaranteed, a documented recovery plan and maintenance window become more important.
Operational controls in Intune
Intune Remediations can schedule detection and trigger remediation when detection reports an issue. The configured run context and 32-bit versus 64-bit PowerShell option influence results. Rollout should begin with pilot devices, compare the before-and-after state and monitor errors before expanding. A change may also be enforced by Group Policy or another management tool, leading to configuration conflict. Resolve ownership before repeatedly pushing a setting that another policy undoes. VulnOps is intended to help generate and validate the artifacts, not substitute for change approval or device-level telemetry. The engineering lesson is simple: a successful automation is one whose outcome can be independently observed, whose failures are legible and whose behaviour remains boring on the second execution.
Engineering review checklist
Before using this approach in production, document the affected versions, prerequisite access, approval owner, intended change, test evidence, rollback limitations and independent validation criteria. Revisit the outcome after the next scan cycle. These checks help distinguish a successful script execution from a defensible security decision and prevent an incomplete change from being reported as closed.
