How OpenLogi Ensures DMG Integrity Using Minisign Signatures in the Release Updater
OpenLogi's release updater verifies DMG integrity by embedding a base64-encoded minisign public key at build time and enforcing strict signature verification at runtime using the minisign-verify crate, rejecting any artifacts that fail cryptographic validation.
The AprilNEA/OpenLogi repository implements a secure macOS update mechanism through the gpui-updater crate, ensuring that every DMG artifact distributed to users is cryptographically signed and verified before installation. This design leverages the minisign signature scheme to protect against tampered binaries, with the public key injected during the CI build process and enforced through strict verification policies at runtime.
Build-Time Public Key Embedding
The foundation of OpenLogi's security model relies on compile-time embedding of the minisign public key, ensuring the key is immutable once the binary is distributed.
The MINISIGN_PUBLIC_KEY Constant
In crates/openlogi-desktop/src/platform/updater.rs (lines 28-31), the public key is captured from the build environment using Rust's option_env! macro:
/// Base64 minisign public key, embedded at build time by the release workflow.
const MINISIGN_PUBLIC_KEY: Option<&'static str> =
option_env!("OPENLOGI_UPDATE_MINISIGN_PUBLIC_KEY");
This constant reads the OPENLOGI_UPDATE_MINISIGN_PUBLIC_KEY environment variable provided by the CI pipeline. For local development builds where this variable is absent, the constant resolves to None, triggering a fail-closed behavior that prevents unverified updates.
Runtime Key Retrieval
The minisign_public_key() function (lines 72-78 in the same file) handles the extraction of the embedded key:
fn minisign_public_key() -> Option<String> {
MINISIGN_PUBLIC_KEY.map(|s| {
s.trim().to_string()
})
}
This function returns None for development builds or the trimmed, base64-decoded public key string for release binaries built in CI.
Runtime Verification Architecture
The updater configures strict verification policies that mandate both SHA-256 manifest checksums and minisign signature validation before any DMG can be installed.
Engine Configuration with Strict Verification
When initializing the updater, the code constructs an EngineConfig with Verification::Strict enforced. As implemented in crates/openlogi-desktop/src/platform/updater.rs (lines 64-70):
let mut config = EngineConfig::new(version).verification(Verification::Strict);
if let Some(key) = minisign_public_key() {
config = config.minisign_public_key(key);
}
let updater = Updater::new(source, config, cx);
The Verification::Strict setting requires both manifest integrity checks and cryptographic signature verification. The configuration is enriched with minisign_public_key(key) only when a valid key is present, ensuring production builds enforce signature validation while development builds fail safely.
Signature Verification Flow
At runtime, the updater executes a four-step verification sequence:
- Manifest Retrieval: Downloads the static
latest.jsonmanifest that lists the appropriate artifact for the current OS/architecture combination. - Artifact Download: Retrieves both the DMG file and its companion
.minisigsignature file. - Cryptographic Verification: Calls the minisign-verify library to validate that the DMG's signature matches the embedded public key.
- Conditional Exposure: Only exposes the update to the user or proceeds with auto-installation after successful verification.
If the public key is missing—which occurs in local development builds—the updater returns an error immediately, preventing any unverified artifact from reaching the user.
CI/CD Signing Process
The integrity guarantee depends on the signing process executed during the release workflow, defined in .github/workflows/release.yml (lines 274-275).
Minisign Signing Commands
The CI pipeline signs each artifact using the minisign private key stored as a secret, then immediately verifies the signature using the public key:
# Sign the artifact (e.g., the .dmg file)
minisign -S -m "$artifact" -s "$key_file" -x "$artifact.minisig" -W
# Verify immediately to fail the job if signing is invalid
minisign -V -m "$artifact" -P "$OPENLOGI_UPDATE_MINISIGN_PUBLIC_KEY" -x "$artifact.minisig"
The -S flag initiates signing, -m specifies the message (artifact) file, -s provides the private key path, and -x outputs the signature file. The subsequent verification step ensures that any corruption or signing errors are caught before the release is published.
Public Key Injection
The OPENLOGI_UPDATE_MINISIGN_PUBLIC_KEY environment variable is injected into the build environment during the CI workflow, ensuring that release binaries contain the correct public key for future verification of updates.
Security Guarantees and Fail-Closed Design
OpenLogi's updater implements a fail-closed security posture. When the minisign_public_key() function returns None—as it does in builds where the environment variable is not set—the updater cannot construct a valid verification configuration. This prevents the installation of any artifact that lacks a valid minisign signature, protecting users from:
- Man-in-the-middle attacks during download
- Compromised release artifacts
- Accidental installation of development or test builds in production
According to the source code in crates/openlogi-desktop/src/platform/updater.rs, this design ensures that only releases signed with the trusted minisign key distributed through the official CI pipeline can be applied to user systems.
Summary
- OpenLogi embeds a base64-encoded minisign public key at compile time via the
OPENLOGI_UPDATE_MINISIGN_PUBLIC_KEYenvironment variable, stored in theMINISIGN_PUBLIC_KEYconstant incrates/openlogi-desktop/src/platform/updater.rs. - The
minisign_public_key()function extracts this key for production builds while returningNonefor local development builds. - The updater configures
EngineConfigwithVerification::Strictand registers the public key viaconfig.minisign_public_key(key)to enforce cryptographic verification. - The minisign-verify crate validates DMG artifacts against their
.minisigcompanions before exposing updates to users. - The CI workflow in
.github/workflows/release.ymlsigns artifacts usingminisign -Sand verifies them immediately withminisign -Vbefore distribution. - The system fails closed when verification is impossible, ensuring unverified artifacts cannot be installed.
Frequently Asked Questions
What happens if the minisign public key is not embedded in the binary?
If the OPENLOGI_UPDATE_MINISIGN_PUBLIC_KEY environment variable is absent during the build process, the MINISIGN_PUBLIC_KEY constant resolves to None and the minisign_public_key() function returns None. In this scenario, the updater cannot complete strict verification and returns an error, preventing the installation of any unverified DMG artifacts. This fail-closed behavior protects users from installing potentially compromised updates in development environments.
Which files are involved in the signature verification process?
The verification process involves three components: the DMG artifact itself (e.g., OpenLogi-1.0.0.dmg), the detached signature file with the .minisig extension (e.g., OpenLogi-1.0.0.dmg.minisig), and the embedded public key constant in the binary. The updater retrieves both the DMG and its .minisig companion from the release source, then uses the minisign-verify library to validate that the signature was created with the private key corresponding to the embedded public key.
Where is the minisign signing implemented in the CI pipeline?
The signing logic resides in .github/workflows/release.yml at lines 274-275. The workflow executes minisign -S to sign each artifact with the private key stored in repository secrets, followed immediately by minisign -V to verify the signature against the OPENLOGI_UPDATE_MINISIGN_PUBLIC_KEY variable. This ensures that only properly signed artifacts are attached to GitHub releases and distributed to users.
How does the updater handle signature verification failures?
When the minisign-verify library detects a signature mismatch, invalid signature format, or missing signature file, the verification returns an error before the DMG is exposed to the user or installed automatically. Because the EngineConfig uses Verification::Strict mode, any cryptographic validation failure halts the update process entirely, ensuring that only artifacts passing both SHA-256 checksum validation and minisign signature verification can be installed on macOS systems.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →