Sparkle 2

repository·2.x·Indexed 27 days ago

https://github.com/sparkle-project/sparkle

A secure and reliable software update framework for macOS. Sparkle 2 provides features such as delta updates, sandboxing support, and custom UIs. It includes the BinaryDelta CLI for creating and applying binary delta patches, an Ed25519 implementation for cryptographic signing and key exchange, and a core API featuring SPUStandardUpdaterController, SPUUpdater, and SPUUserDriver.

Tokens
7.1K
Snippets
9
Records
43
Agent score
90%

What's inside Sparkle

  1. Security and IPC architecture of the Sparkle Installer

    2.x

    The Sparkle installer is designed with a zero-trust model regarding the updater process. To ensure security, the installer process performs its own extraction, validation, and installation tasks within a single process. The launcher component (which may run as an XPC service) does not trust the updater to provide paths for the installer or the agent tool.

    Key security and operational behaviors:

    • Process Isolation: The installer does not trust the updater for critical paths or communication speed.
    • Timeouts: Sparkle uses timeouts and ping/pong messages to handle potential communication delays or connection invalidation issues, particularly on older macOS systems.
    • Termination Behavior: When the application terminates before final installation, Sparkle sends an Apple quit event to all running application instances found within the agent's GUI login session. It does not attempt to terminate instances in other logged-in sessions.
    • Single Instance Limitation: The installer currently only watches a single process identifier for termination; it does not handle cases where new instances are launched after the initial watch begins.
  2. Understand Sparkle Installer IPC and Security Components

    2.x

    Sparkle's update process involves several distinct components working together via Inter-Process Communication (IPC) to ensure secure and reliable updates:

    • The bundle to update & replace: The target application or plugin being updated.
    • The application to listen for termination & to relaunch: The process that Sparkle monitors for termination and subsequently relaunches. This may be the same as the bundle being updated, or a separate host application (e.g., a plugin host).
    • The updater (Sparkle.framework): Responsible for scheduling, downloading updates, and initiating the installer.
    • The installer (Autoupdate): A separate program submitted by the updater. It performs extraction, validation, and installation. It runs as a launchd agent or daemon, depending on whether elevated permissions are required.
    • The progress or agent application: Hosts the installation status service, displays the installation UI for long-running updates, and is responsible for launching the new update after completion.
  3. Core Sparkle 2 API components

    2.x

    Sparkle 2 provides several primary classes and protocols to manage the update lifecycle. Depending on your requirements, you will interact with one or more of the following:

    • SPUStandardUpdaterController: The recommended way to create a standard updater. It encapsulates both an SPUUpdater and a SPUStandardUserDriver to provide a complete update experience.
    • SPUUpdater: Used for invoking update checks and retrieving updater properties.
    • SPUUpdaterDelegate: A protocol providing delegation methods to control the behavior of an SPUUpdater instance.
    • SPUUserDriver: An interface for creating custom user interfaces for the update process.

    If you are migrating from Sparkle 1, focus on SPUStandardUpdaterController and SPUUpdater.

  4. Understand the Installer IPC and Security Model

    2.x

    Sparkle uses an Inter-Process Communication (IPC) model involving an updater driver, an installer, and a progress agent.

    Key Components

    • Updater Driver: Initiates the update process. It can be UI-based (interactive) or automatic (silent).
    • Installer: A standalone executable responsible for extraction, validation, and the three stages of installation. It may require root privileges depending on the installation type (e.g., guided/regular packages require root; normal application updates only require root if write permissions are insufficient).
    • Progress Agent: A helper application used to display progress UI and manage the target application's lifecycle. It is copied to a temporary cache location to ensure it remains available even if the original application bundle is moved or removed during installation.

    Security and Sandboxing

    • XPC Service: Used to launch the installer, especially for sandboxed applications.
    • File Ownership: The installer moves downloaded updates into its own managed update directory to prevent attackers from manipulating files during the installation process and to ensure the installer 'owns' the update.
    • Validation: The installer verifies that the archive's contents match the expected installation type defined in the appcast. For delta updates, EdDSA signature validation is performed before extraction.
  5. Implement XPC Services in Sparkle

    2.x

    If you are implementing or working with XPC services in Sparkle, follow these constraints to ensure compatibility and avoid retain cycles:

    1. Avoid Protocol Inheritance: XPC protocols must not adopt other protocols (e.g., protocol A : B). The XPC protocol decoder on older supported systems may fail to find methods if inheritance is used.
    2. Manual Invalidation: Because XPC services are optional and code must be usable directly from the framework, classes used in services that take a delegate must not use a weak reference for that delegate. Instead, you must break retain cycles explicitly using a custom invalidate method.
    3. Cleanup: Do not implement dealloc for cleanup; use the custom invalidate method instead.
    4. Service Recommendation: For most developers, it is recommended to set up a temporary exception with your bundle ID rather than using the InstallerConnection or InstallerStatus proxy services.
  6. Extensibility via Composition instead of Subclassing

    2.x

    Sparkle 2.0 has moved away from subclassing. Subclassing internal (non-exported) classes is no longer supported and is discouraged for all classes to ensure maintainability.

    To extend functionality, use composition and the provided user driver API. The internal update drivers follow a protocol-oriented approach to facilitate this.

  7. Integrate ed25519-sparkle into your project

    2.x

    You can integrate this Ed25519 implementation in two ways:

    1. Source Integration: Add all .c and .h files from the src/ folder directly to your project and include ed25519.h.
    2. Shared Library: Copy only ed25519.h and define the ED25519_DLL macro before importing it.

    Note on Portability: The implementation uses standard OS cryptography APIs (CryptGenRandom on Windows, /dev/urandom on nix) for seed generation. If you need to be entirely portable without OS dependencies, define ED25519_NO_SEED. This disables ed25519_create_seed, requiring you to provide your own 32-byte cryptographic random seed.

  8. Sparkle 2 Requirements

    2.x

    Before integrating Sparkle 2, ensure your environment meets the following requirements:

    • Runtime: macOS 12.0 or later (for 2.x versions); macOS 10.13 or later (for 2.9.3).
    • Build Environment: The latest major Xcode (stable or beta) and one major version prior.
    • Server: An HTTPS server must be used to serve updates (ensure compliance with App Transport Security).
  9. Security requirements for update installation

    2.x

    To maintain a secure update model in Sparkle 2.0, follow these architectural principles:

    • Privilege Separation: Sparkle splits tasks across several components (User Driver, Updater Scheduler, XPC Services, Progress Agent, and Installer) to allow them to run in different processes.
    • Installer Responsibility: The installer must handle extraction, validation, and installation within a single process. It should not rely on AuthorizationExecuteWithPrivileges.
    • Signature Verification: Because the installer does not handle downloading, it cannot trust the download protocol (e.g., HTTP vs HTTPS). You must use EdDSA signatures/keys to verify updates; applying updates without an EdDSA signature is deprecated.
    • Code Signing: If XPC Services and Autoupdate are code-signed, they may reject connections if the client is not signed with the same Team ID.
  10. Understand the Three Stages of Installation

    2.x

    The installer executes the update in three distinct stages:

    Stage 1: Initial Preparation

    • Regular Application Installer: Performs initial work such as clearing quarantine, changing owner/group, updating modification dates, and invoking GateKeeper scans. (Note: This is skipped if the bundle must be transferred to another volume).
    • Guided Package Installer: Does nothing in Stage 1.

    Stage 2: Application Termination

    • The installer waits for the target application to terminate.
    • If the application is still running, the installer requests the progress agent to send an Apple 'quit' event to the application.
    • Once the application is terminated, the installer proceeds to Stage 3.

    Stage 3: Final Replacement

    • Performs the final installation work of updating and replacing the old bundle with the new one.
    • After success, the installer signals the agent to stop showing progress and may request a relaunch of the new application.
  11. Build a Sparkle distribution package

    2.x

    If you need to build a Sparkle distribution (e.g., after making changes to the Sparkle source code), you can use one of the following methods:

    Using Make: Navigate to the root of the Sparkle source tree and run:

    make release

    This will create a Sparkle-*VERSION*.tar.xz file.

    Using Xcode: Build the Distribution scheme directly within the Xcode UI.

  12. Best practices for Delegation in Sparkle

    2.x

    When implementing delegation patterns compatible with Sparkle's architecture:

    1. Avoid passing the delegator: Do not pass the delegator object around to other components.
    2. Handle Return Types: If you define optional delegate methods that have return types, ensure they are either truly optional or have known default values for primitive types.