Skip to content

fix(macos): retain runtime protections and updater blocking - #4016

Merged
afonsojramos merged 5 commits into
v3-betafrom
fix/macos-signing-metadata
Oct 5, 2026
Merged

afonsojramos merged 5 commits into
v3-betafrom
fix/macos-signing-metadata

Conversation

@afonsojramos

Copy link
Copy Markdown
Member

Summary

Keep Spotify's Hardened Runtime metadata intact after macOS Apply, and keep the requested updater block effective without rewriting clean executables. The previous ad-hoc signer stripped runtime metadata, while the legacy immutable cache directory did not cover the current updater's staging location.

The signing fix and update-protection replacement are separate commits so they can be assessed independently.

Decisions and migration

  • Preserve each executable's own entitlements, signing flags, and runtime version. Do not transplant main-app entitlements to helpers or preserve identity-dependent requirements. This prevents future stripping; it cannot reconstruct metadata already lost.
  • Protect both current Update and legacy PersistentCache/Update staging directories. Clear already-prepared updates and verify physical protection rather than trusting configuration. Native download controls showed that the legacy directory alone did not stop downloading, while protecting the current directory did; unlocking and relaunching restored downloading.
  • Keep durable user intent separate from the temporary updater aperture. Restore legacy endpoint patches only after securing directories when blocking, and before opening directories when unblocking. Retain the original executable outside the bundle through signing, stage and flush replacements before atomic rename, and retry interrupted migrations from the recovery image.

Ordinary Apply still signs modified resources independently of update blocking. Linux/Windows protection paths and native-update platform guards retain their existing behavior.

Validation

Local verification used arm64 macOS 26.6.2, Rust 1.98.0, and official Spotify 1.3.3.264. Project toolchain settings were not changed.

  • Workspace tests: 221 passed, 5 ignored, with four test threads.
  • Native fixtures exercise distinct per-executable metadata, repeated signing, JIT execution, actual immutable-directory write/remove/rename denial, legacy migration, partial-write failure, interrupted/missing-image recovery, and no-op changes with a running stand-in.
  • The ignored official-bundle regression passed on a private copy, comparing every Mach-O file's metadata after repeated finalization and checking strict signatures and Gatekeeper policy. It does not launch Spotify.
  • Normal CLI block/status/unblock commands passed with a private HOME and endpoint-free fixture, including durable intent, idempotence, actual write denial, and symlink failure reporting.
  • Formatting, production workspace Clippy with -D warnings, and CLI/daemon builds passed. Neither binary was installed or started.

All-target Clippy remains blocked by 48 pre-existing test-lint errors. One unrestricted parallel run failed the existing daemon instance-lock timing test; the final four-thread run passed. The installed Spotify executable hash, profile/configuration, running daemon, and existing update protection were not changed by fix validation.

Outstanding before ready

This PR is a draft, not end-to-end or release clearance.

  • Native Intel macOS signing/JIT and launch verification.
  • Actual Spotify playback and helper library loading after preserved signing.
  • Full native Manager Update & Apply, cancellation/recovery, installation, restart, returned patched UI, and final protection verification on the combined source.
  • Linux/Windows CI and runtime verification.
  • Nested signing failure after some helpers have been re-signed. Recovery currently retains the main executable, not a transactional original copy of the entire bundle.

Symlinked staging ancestors are deliberately rejected. Relocated-cache configurations must resolve to the directories Spotify actually uses; the default-path checks do not prove those configurations.

Protect current and legacy staging directories and verify their physical state.
Migrate legacy endpoint patches with a recoverable original and atomic replacement.
Keep durable intent separate from temporary apertures and ordinary Apply signing.
@coderabbitai

coderabbitai Bot commented Oct 4, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: Repository: spicetify/cli/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: b269a062-d399-4a49-bc64-3e5e3b81bc47

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@afonsojramos

afonsojramos commented Oct 4, 2026 •

Copy link
Copy Markdown
Member Author

Intel macOS test build. Paste this into Terminal, with GitHub CLI (gh) installed and signed in:

bash <<'SCRIPT'
set -e
work="$(mktemp -d)"
dest="$HOME/.spicetify"

gh run download 37212773310 --repo spicetify/cli \
  --name spicetify-pr-macos-x86_64-964f1c3d5798646ba4b5d820e1c754ab3ecc6d50 \
  --dir "$work"

"$dest/spicetify" daemon stop
cp -p "$dest/spicetify" "$dest/spicetify-daemon" "$work/"
printf 'Previous binaries backed up to: %s\n' "$work"
printf 'Quit Spotify, replace Spotify.app with a fresh official copy, then press Enter: '
read -r </dev/tty

tar -xzf "$work/spicetify-pr-macos-x86_64-964f1c3d5798.tar.gz" -C "$dest"
"$dest/spicetify" spotify-updates block
"$dest/spicetify" apply
SCRIPT

Then test playback and restarting Spotify. The fresh Spotify copy matters because the fix cannot recover signing metadata already stripped by an older build.

@afonsojramos
afonsojramos marked this pull request as ready for review October 5, 2026 14:20
@afonsojramos
afonsojramos merged commit 4389f7a into v3-beta Oct 5, 2026
7 checks passed
@afonsojramos
afonsojramos deleted the fix/macos-signing-metadata branch October 5, 2026 14:20
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