Skip to content

Never write the log through a planted link, and show the release version in the app header - #12

Merged
rodchristiansen merged 2 commits into
mainfrom
fix/filelog-no-links
Oct 7, 2026
Merged

rodchristiansen merged 2 commits into
mainfrom
fix/filelog-no-links

Conversation

@rodchristiansen

@rodchristiansen rodchristiansen commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Why

%ProgramData%\ManagedNotifications\logs stays user-writable so user-context dialog runs can log. dialog.exe can also run as SYSTEM, for example when a management tool calls it before anyone signs in. A link a user left in logs would then turn the log append into a SYSTEM write somewhere else.

What

  • SafeLogFile (copied from manageusers):
    • RemoveLinks deletes any symbolic link or junction from the data root down to the log. Only the link goes, never its target.
    • OpenAppend opens with FILE_FLAG_OPEN_REPARSE_POINT. If the file is a reparse point or has more than one name (a hard link), it deletes that name and creates a new file.
  • FileLog.Write calls RemoveLinks before it creates the folder, migrates or rotates, then appends through OpenAppend instead of File.AppendAllText. The line format, rotation and never-throw behaviour are unchanged.

Tests

32 pass. There are 7 new tests:

  • 5 copied from manageusers: plain append, junctioned folder, junction at the root, hard link, and symbolic link (skipped without privilege).
  • 2 run through FileLog itself: a hard-linked log file, and a junctioned logs folder.

FileLog tests share a collection so the static log path is not changed while another test reads it.

Also: release version in the header

  • The Prefs header showed the build time, from a BuildTimestamp stamped at compile time. It now shows AssemblyInformationalVersion with the +sha suffix stripped, zero-padded to YYYY.MM.DD.HHMM (ReleaseVersion.Display, 7 tests). This matches crypt-escrow Prefs: replace the Managed badge with one policy note and list installed services #19.
  • build.ps1 -Version sets the release version, and release.yml passes the tag, so the header, MSI and .pkg carry the tag rather than the build time. With no -Version it falls back to the current time, as before.
  • Checked: build.ps1 -Msi -Version 2026.10.06.2105 produces an app whose ProductVersion is 2026.10.06.2105+<sha>, which the header shows as 2026.10.06.2105. The suite now has 39 passing tests.

The logs folder stays user-writable for user-context runs, and dialog.exe can run as
SYSTEM. FileLog now removes any symbolic link or junction between the data root and
the log before creating anything, opens the log without following a reparse point,
and replaces a log that is a link or has a second name (a hard link) with a fresh
file. SafeLogFile is copied from manageusers.
The Prefs header read a BuildTimestamp stamped at compile time. It now shows the
informational version without its +sha suffix, zero-padded to YYYY.MM.DD.HHMM.
build.ps1 takes -Version, and the release workflow passes the tag, so the header,
the MSI and the .pkg all carry the release version.
@rodchristiansen rodchristiansen changed the title Never write the diagnostic log through a link a user planted in logs Never write the log through a planted link, and show the release version in the app header Oct 7, 2026
@rodchristiansen
rodchristiansen merged commit 50d4364 into main Oct 7, 2026
1 check passed
@rodchristiansen
rodchristiansen deleted the fix/filelog-no-links branch October 7, 2026 03:49
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