Fix: CWE 428 - #2168
Conversation
- Update NSIS installer to register service with properly quoted executable path - Add runtime self-heal in portmaster-core on Windows service startup to protect users who update via in-app updater without re-running the installer safing/portmaster-shadow#43
📝 WalkthroughWalkthroughThis PR adds Windows service registry self-heal logic to PortmasterCore, updates the NSIS installer to properly quote service paths during installation, and bumps the desktop application version to 2.1.19 across Angular and Cargo manifests. ChangesService Path Registry Management and Release
🎯 2 (Simple) | ⏱️ ~12 minutes 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@cmds/portmaster-core/main_windows.go`:
- Around line 68-73: The code uses strings.Index on imagePath to find ".exe"
which can match occurrences in parent folder names; change this to search for
".exe" only after the last path separator so we detect the executable boundary
correctly. Concretely, compute lastSep := strings.LastIndexAny(imagePath, `\/`),
then call strings.Index on strings.ToLower(imagePath[lastSep+1:]) (adjusting
exeEnd relative to the whole string) to set exeEnd, and keep the same error
handling if no .exe is found; update references to exeEnd/imagePath accordingly
so truncation and subsequent matching use the boundary-aware index.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: f7de2ae2-4965-45ae-aee4-d2bf68a1237c
⛔ Files ignored due to path filters (2)
desktop/angular/package-lock.jsonis excluded by!**/package-lock.jsondesktop/tauri/src-tauri/Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (4)
cmds/portmaster-core/main_windows.godesktop/angular/package.jsondesktop/tauri/src-tauri/Cargo.tomldesktop/tauri/src-tauri/templates/nsis/install_hooks.nsh
| // Unquoted path detected. Locate the end of the executable (.exe boundary). | ||
| exeEnd := strings.Index(strings.ToLower(imagePath), ".exe") | ||
| if exeEnd < 0 { | ||
| return fmt.Errorf("ImagePath contains no .exe, skipping fix: %s", imagePath) | ||
| } | ||
| exeEnd += len(".exe") |
There was a problem hiding this comment.
Use boundary-aware executable parsing to avoid self-heal false negatives
Line 69 takes the first .exe anywhere in ImagePath. If a parent folder contains .exe (for example C:\foo.exe\Portmaster\portmaster-core.exe ...), Line 75 truncates the path and Line 85 fails the match, so the vulnerable unquoted value is never repaired.
Suggested patch
- // Unquoted path detected. Locate the end of the executable (.exe boundary).
- exeEnd := strings.Index(strings.ToLower(imagePath), ".exe")
+ // Unquoted path detected. Locate the executable boundary (.exe followed by
+ // whitespace or end-of-string), not just the first ".exe" substring.
+ lowerPath := strings.ToLower(imagePath)
+ exeEnd := -1
+ for i := 0; i < len(lowerPath); {
+ idx := strings.Index(lowerPath[i:], ".exe")
+ if idx < 0 {
+ break
+ }
+ idx += i
+ boundary := idx + len(".exe")
+ if boundary == len(lowerPath) || lowerPath[boundary] == ' ' || lowerPath[boundary] == '\t' {
+ exeEnd = boundary
+ break
+ }
+ i = idx + 1
+ }
if exeEnd < 0 {
return fmt.Errorf("ImagePath contains no .exe, skipping fix: %s", imagePath)
}
- exeEnd += len(".exe")📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Unquoted path detected. Locate the end of the executable (.exe boundary). | |
| exeEnd := strings.Index(strings.ToLower(imagePath), ".exe") | |
| if exeEnd < 0 { | |
| return fmt.Errorf("ImagePath contains no .exe, skipping fix: %s", imagePath) | |
| } | |
| exeEnd += len(".exe") | |
| // Unquoted path detected. Locate the executable boundary (.exe followed by | |
| // whitespace or end-of-string), not just the first ".exe" substring. | |
| lowerPath := strings.ToLower(imagePath) | |
| exeEnd := -1 | |
| for i := 0; i < len(lowerPath); { | |
| idx := strings.Index(lowerPath[i:], ".exe") | |
| if idx < 0 { | |
| break | |
| } | |
| idx += i | |
| boundary := idx + len(".exe") | |
| if boundary == len(lowerPath) || lowerPath[boundary] == ' ' || lowerPath[boundary] == '\t' { | |
| exeEnd = boundary | |
| break | |
| } | |
| i = idx + 1 | |
| } | |
| if exeEnd < 0 { | |
| return fmt.Errorf("ImagePath contains no .exe, skipping fix: %s", imagePath) | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@cmds/portmaster-core/main_windows.go` around lines 68 - 73, The code uses
strings.Index on imagePath to find ".exe" which can match occurrences in parent
folder names; change this to search for ".exe" only after the last path
separator so we detect the executable boundary correctly. Concretely, compute
lastSep := strings.LastIndexAny(imagePath, `\/`), then call strings.Index on
strings.ToLower(imagePath[lastSep+1:]) (adjusting exeEnd relative to the whole
string) to set exeEnd, and keep the same error handling if no .exe is found;
update references to exeEnd/imagePath accordingly so truncation and subsequent
matching use the boundary-aware index.
Summary by CodeRabbit
Bug Fixes
Chores