Skip to content

fix: all-users (Common) startup-folder toggles target HKLM, not HKCU#1430

Merged
laurentiu021 merged 1 commit into
mainfrom
fix/startup-common-folder-hklm
Jul 10, 2026
Merged

fix: all-users (Common) startup-folder toggles target HKLM, not HKCU#1430
laurentiu021 merged 1 commit into
mainfrom
fix/startup-common-folder-hklm

Conversation

@laurentiu021

Copy link
Copy Markdown
Owner

Summary

Fresh ultra-audit finding (services-O-S, P2), verified against current source.

Both the per-user Startup folder and the all-users Common Startup folder were scanned and tagged with the same StartupSource.StartupFolder. So ApplyApprovedState read the enabled/disabled state for all folder items only from HKCU, and SetEnabledAsync wrote the toggle blob for all folder items only to HKCU. But Windows stores the StartupApproved\StartupFolder state for all-users shortcuts under HKLM.

Consequences for a shortcut in %ProgramData%\...\Startup:

  • An item disabled via Task Manager (HKLM blob) was shown as "Enabled" (wrong state).
  • Disabling it in SysManager wrote the disable blob to HKCU — where Windows never looks for common-folder state — so it returned success while the program still launched at logon.

For a startup manager, a disable that reports success but doesn't disable is a trust/correctness defect.

Fix

  • Added StartupSource.CommonStartupFolder, set in ReadStartupFolder based on which special folder produced the entry (SpecialFolder.Startup vs SpecialFolder.CommonStartup).
  • ApplyApprovedState now reads HKLM's StartupApproved\StartupFolder for common-folder entries.
  • SetEnabledAsync routes common-folder entries to HKLM (needs administrator — a non-elevated attempt surfaces the existing "requires elevation" message, exactly like the HKLM Run path).
  • Per-user folder items are completely unchanged.

Regression tests

  • BuildStartupFolderEntry_Common_TaggedCommonStartupFolderisCommon: trueCommonStartupFolder.
  • BuildStartupFolderEntry_PerUser_TaggedStartupFolderisCommon: falseStartupFolder.

Both are red before the fix (the isCommon parameter and the CommonStartupFolder enum value did not exist). The hive routing depends entirely on this source tagging. (No test writes the registry — the toggle's HKLM write path needs elevation and would mutate real machine state, so it's excluded from the CI-safe unit suite.)

Checks

  • All 3 projects build 0 warnings / 0 errors
  • Leak scan on diff: clean

Both the per-user Startup folder and the all-users Common Startup folder were scanned
and tagged with the same StartupSource.StartupFolder, so ApplyApprovedState read the
enabled/disabled state for ALL folder items only from HKCU and SetEnabledAsync wrote
the toggle blob for ALL folder items only to HKCU. Windows stores the
StartupApproved\StartupFolder state for all-users shortcuts under HKLM. So for a
shortcut in %ProgramData%\...\Startup: an item disabled via Task Manager (HKLM blob)
showed as 'Enabled', and disabling it in SysManager wrote to HKCU where Windows never
looks — returning success while the program still launched at logon.

Added StartupSource.CommonStartupFolder (set in ReadStartupFolder from which special
folder produced the entry). ApplyApprovedState now reads HKLM for common-folder
entries; SetEnabledAsync routes them to HKLM (needs elevation — a non-elevated
attempt surfaces the existing 'requires elevation' message). Per-user items unchanged.

Fixes ultra-audit finding P2 #38.

Regression tests: BuildStartupFolderEntry_Common_TaggedCommonStartupFolder and
BuildStartupFolderEntry_PerUser_TaggedStartupFolder pin the source tagging (the
discriminator the hive routing depends on). Red before (the isCommon param and the
CommonStartupFolder enum value did not exist).
@laurentiu021 laurentiu021 merged commit dc428a6 into main Jul 10, 2026
4 checks passed
@laurentiu021 laurentiu021 deleted the fix/startup-common-folder-hklm branch July 10, 2026 22:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant