Harden the update watchdog and broaden what it re-asserts - #47
Merged
Merged
Conversation
The watchdog task runs its payload as SYSTEM, but the payload lived in %ProgramData%\Winnow with the default inherited ACL, which lets a standard user influence a script SYSTEM later executes. Lock that directory down (SYSTEM and Administrators full, users read and execute, inheritance off) and re-apply the ACL on every run. Record the payload's SHA256 under an admin-only HKLM key at install and re-check it before enforcing, so a swapped payload refuses to run instead of applying whatever it now contains; missing or unreadable state fails closed. The old payload only re-asserted AllowTelemetry and DiagTrack. It now re-asserts the machine-wide privacy floor Windows Update most often resets: the Copilot, Recall, Windows AI, generative fill, cross-device clipboard, ink workspace, and OneDrive sync policies, dmwappushservice, and the CEIP telemetry tasks, correcting only what has drifted. Kept to HKLM because a SYSTEM task has no user hive. Moved the payload out of the here-string into Scripts/Watchdog/WatchdogPayload.ps1 so it can be parsed and unit-tested. Added Tests/Unit/Test-UpdateWatchdog.ps1 covering the ACL, the integrity check, and the drift-only enforcement, and wired it into the CI workflow.
This was referenced Sep 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
The
-EnableUpdateWatchdogtask runs its payload as SYSTEM, but the payload lived in%ProgramData%\Winnowunder the default inherited ACL, which a standard user can influence. A SYSTEM task executing a script from a directory non-admins can write to is a local privilege-escalation path.This reworks the watchdog into a tamper-evident, broader-coverage self-healing enforcer:
%ProgramData%\Winnowgets a protected ACL (SYSTEM + Administrators Full Control, standard users read/execute, inheritance off), re-applied on every run.HKLM\SOFTWARE\Winnow\Watchdogkey at install and re-checked before enforcing. A payload that does not match refuses to run and logs a warning; missing/unreadable state fails closed.AllowTelemetry+DiagTrack, it now re-asserts the machine-wide (HKLM) privacy policy floor Windows Update most often resets: Copilot, Recall, Windows AI, generative fill, cross-device clipboard, ink workspace, and OneDrive sync policies,dmwappushservice, and the CEIP telemetry tasks. Touches only what has drifted. Kept toHKLMbecause a SYSTEM task has no user hive.Scripts/Watchdog/WatchdogPayload.ps1so it is parsed by static validation and unit-tested.Validation
Run locally on Windows PowerShell 5.1:
Tests\Invoke-StaticValidation.ps1 -RequirePSScriptAnalyzer— parse, duplicate-function, JSON, and PSScriptAnalyzer at Error severity: clean (120 files).Tests/Unit/Test-UpdateWatchdog.ps1(Pester 5.7.1): 11/11 pass (ACL protection, integrity pass/tamper/missing/absent, desired-state shape, drift-only enforcement for registry/service/task).Test-DesiredStateVerification,Test-CustomFeatureContracts,Test-SafetyGuards): 35/35 pass, no regressions.build.ps1standalone builds and parses clean with the newScripts/Watchdogfolder embedded.Not verified here (needs a live environment, unchanged from prior watchdog work): the end-to-end path against a real Windows update installing and the watchdog firing on the event trigger as SYSTEM. Documented as a known limitation in the CHANGELOG entry.
New CI step added to run the watchdog tests.