Security & code audit — repojacking fix, crash fix, hardening#46
Merged
Conversation
Security: - Auto-updater now targets the repository current name (Daolyap/Money-Shot). The old name only redirects until someone re-registers it, at which point they would own the update channel (repojacking). - Optional GitHub token properly wired to MONEYSHOT_GITHUB_TOKEN (the 401 guidance already referenced it; the read was a disabled empty-string stub). - SaveService system-directory check compares with a trailing separator so C:\Windows blocks C:\Windows\... but not C:\WindowsBackup siblings. - HistoryRetentionCount clamped to 0-500 during settings sanitization. Bugs: - Second app instance crashed on exit: OnExit called ReleaseMutex on the single-instance mutex it never owned (ApplicationException). - Hotkey actions that throw no longer propagate out of the WndProc hook (process-fatal); they are caught and logged. Registration failures (combination owned by another app) are now logged instead of silent. - Editor Save dialog now honours the configured default save folder and file format; previously both settings were ignored. - IsPointInElement used hand-rolled NaN guards instead of CanvasPosition (forbidden by the resize/drag design rules). Improvements: - MemoryTrimmer service shared by both editor-close paths; opening a capture from History now gets the same working-set trim as the capture flow (previously left ~hundreds of MB resident). - JPEG saves use QualityLevel 90 (default 75 smears screenshot text). - Logger includes full exception + stack trace at Error level. - Dead SetupToolbar() removed; App.xaml.cs unused usings dropped. - 14 new regression tests (SaveService path validation, retention clamp); 109/109 passing. Audit follow-ups recorded in Opus-Speaks.md: region-selector DPI accuracy at >100% scaling (E2), auto-update vs per-machine installs (E3). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
Summary
Full security and code audit of the service layer and window code-behind, stacked on top of #45 (
Fable/Overhaul).Security findings (fixed)
MoneyShot→Money-Shot, butAutoUpdateServicestill pointed at the old name. GitHub redirects an old repo name only until someone re-registers it — at which point they control the update channel of every installed copy.Daolyap/Money-Shot(verified the new endpoint serves releases +SHA256SUMS.txt); rule documented in CLAUDE.md.Environment.GetEnvironmentVariable("")— a disabled stub — while the 401 error message told users to configureMONEYSHOT_GITHUB_TOKEN.MONEYSHOT_GITHUB_TOKEN; treated as a secret, never logged.SaveServicesystem-directory check used a bareStartsWith, soC:\Windowsalso matched the unrelatedC:\WindowsBackup.settings.jsoncould setHistoryRetentionCountto arbitrary values.ValidateAndSanitizeSettings.Crash / correctness bugs (fixed)
App.OnExitcalledReleaseMutex()on the single-instance mutex the second instance never owned →ApplicationExceptionon its way out. Now only the owning instance releases.WM_HOTKEYhook tears down the app. Now caught and logged. Hotkey registration failures (combination owned by another app) were silently ignored — now logged.IsPointInElementhand-rolled NaN guards instead of usingCanvasPosition(explicitly forbidden by the repo''s resize/drag rules — historical source of snap-to-(0,0) bugs).Optimisations & quality
MemoryTrimmerservice shared by both editor-close paths — opening a capture from History previously skipped the working-set trim and left hundreds of MB resident.QualityLevel = 90(the default 75 visibly smears screenshot text).Loggerrecords the full exception + stack trace at Error level (message-only lines were rarely diagnosable).SetupToolbar, unused usings).Audited and intentionally unchanged
ScreenshotServiceHBITMAP lifecycle (correct:DeleteObjectinfinally,Freeze()for cross-thread).Follow-ups recorded in Opus-Speaks.md (not fixed here)
Verification
dotnet buildclean, 109/109 tests (14 new: SaveService path validation, retention clamping).🤖 Generated with Claude Code