Skip to content

✨ Use privileged updater helper if needed#1063

Merged
mrkai77 merged 20 commits into
developfrom
updater-fixes
Mar 8, 2026
Merged

✨ Use privileged updater helper if needed#1063
mrkai77 merged 20 commits into
developfrom
updater-fixes

Conversation

@mrkai77
Copy link
Copy Markdown
Owner

@mrkai77 mrkai77 commented Mar 5, 2026

This branch started as a fix for updater failures in non-admin sessions, but it ended up being a full updater hardening pass!

The main change is a new privileged helper, LoopUpdaterHelper, that Loop can use during update installation when the current user session cannot write to the install location. Previously, this could cause the update to fail outright.

Security was a huge focus here. The helper is intentionally strict:

  • Loop and helper communicate over XPC with a shared protocol.
  • The helper validates the caller using bundle identity + code-signing requirement checks.
  • The helper does not accept arbitrary file paths from Loop.
  • Instead, Loop sends a rollback token, and the helper derives/validates all paths itself from trusted context.
  • Rollback IDs are validated (format/length/traversal protection), and derived paths must remain inside trusted staging/rollback roots.
  • The helper validates bundle signatures before privileged swap/restore operations.
  • The helper only allows one active privileged connection at a time.
  • Ownership is explicitly managed: rollback copy gets client uid/gid ownership, installed app gets root ownership.

Installation flow changes in Loop:

  • Added UpdaterAuthorizationCoordinator to manage privileged readiness, Authorization Services rights, one-shot SMJobSubmit, helper calls, timeout handling, and SMJobRemove cleanup.
  • Added permission-state routing (writable, needsElevation, notWritableNoElevationPossible) so install behavior is explicit.
  • Privileged flow now stages and verifies after authorization is granted, then performs privileged atomic swap via helper.
  • Added privileged failure reconciliation + restore path and ownership verification for the installed app.
  • If privileged install cannot proceed, Loop now offers a user-facing fallback to install in ~/Applications instead of hard-failing.

Backup/rollback/indexing behavior changes:

  • Replaced old path helper usage with shared LoopSupportPaths.
  • Added shared staging/backup/rollback path model under ~/Library/Application Support/Loop.
  • Rollback working copies now use Rollback.noindex to avoid Spotlight/app-launcher indexing.
  • Rollback snapshots are archived into .zip backups after swap.
  • Backup manager now:
    • stores backups as .zip,
    • purges legacy non-zip backup artifacts,
    • performs best-effort old-backup cleanup when size exceeds threshold,
    • can prepare restore by unzipping the latest archive into staging.

Performance and reliability improvements:

  • Checksum verification is now streaming SHA-256 (1 MiB chunks) instead of loading full files into memory.
  • Download hash checking now includes explicit file existence/readability guards and byte-count logging.
  • Installer code-sign validation moved from shelling out to codesign to Security framework APIs.
  • Directory size calculation was centralized in a FileManager extension and reused where needed.

@mrkai77 mrkai77 self-assigned this Mar 5, 2026
@mrkai77 mrkai77 changed the title Use privileged updater helper if needed ✨ Use privileged updater helper if needed Mar 5, 2026
@mrkai77 mrkai77 added the Feature label Mar 5, 2026
Copy link
Copy Markdown
Collaborator

@SenpaiHunters SenpaiHunters left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remember to also include the README updates 😄.

If we're fine overall with the try? log, then it can be accepted as is.

Comment thread Loop/Updater/UpdaterAuthorizationCoordinator.swift
Comment thread LoopUpdaterHelper/PrivilegedInstaller.swift Outdated
@mrkai77 mrkai77 merged commit 305c938 into develop Mar 8, 2026
1 check passed
@mrkai77 mrkai77 deleted the updater-fixes branch March 8, 2026 03:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants