Security Model

May 13, 2026 ยท View on GitHub

Hermes Desktop is a native macOS client for Hermes that talks directly to the selected host over SSH.

The host stays the source of truth. The app does not introduce a gateway API, background daemon, local mirror, or separate sync layer.

This document describes the current implementation in this repository. It is not a promise about future packaging, signing, or infrastructure changes.

What Executes Locally

Hermes Desktop runs as a normal macOS app on your Mac.

Local execution includes:

  • the app UI and local state handling
  • /usr/bin/ssh for all host communication
  • a local embedded terminal session that opens an SSH shell to the selected host
  • the built-in update check, which requests the latest Hermes Desktop release metadata from the GitHub Releases API

The app does not install a helper service on the host or on your Mac.

What Executes Remotely Over SSH

Hermes Desktop uses SSH to execute commands on the selected host.

Current remote execution includes:

  • non-interactive python3 - invocations for app features that query or modify Hermes state on the host
  • remote shell startup for the embedded terminal
  • remote hermes CLI invocations for in-app chat and session resume flows

The app therefore depends on the remote SSH environment you already trust:

  • SSH access must already work from Terminal on your Mac
  • python3 must exist on the host for service-style RPC requests
  • hermes must be available on the host's non-interactive SSH PATH for in-app chat and terminal resume workflows

Local State Stored On Your Mac

Hermes Desktop stores a small amount of local state under:

~/Library/Application Support/HermesDesktop

Current files written there include:

  • connections.json Saved connection definitions such as label, SSH alias or host, user, port, and selected Hermes profile
  • preferences.json App preferences and lightweight workspace state such as last-used connection, terminal theme preference, update-check preference, bookmarked remote files, pinned sessions, and workflow presets

These files are written with private file permissions (0600) and the app support directory is created with private directory permissions (0700). They are ordinary JSON files under your macOS user account, not Keychain entries.

The app also creates SSH control sockets under:

/tmp/hd-<uid>

That directory is also created with private directory permissions (0700).

What Is Not Stored Locally

Hermes Desktop does not maintain a local mirror of Hermes host state.

In the current implementation, it does not store these Hermes artifacts as a local source of truth:

  • remote session databases and transcripts
  • remote Kanban databases
  • remote cron job definitions
  • remote Hermes skill directories
  • remote workspace files as a synchronized mirror

Unsaved edits can still exist transiently in app memory while you are working, but the app's design is to read and write the canonical state on the host.

Workflow presets are the notable local exception: they are intentionally stored as lightweight launch helpers on your Mac, scoped to the selected host/profile, and used only to seed a fresh remote Terminal session. They are not a local mirror of remote Hermes state.

Secrets And Credentials

Hermes Desktop does not ask you to enter an SSH password into the app.

Current connection profiles store routing details such as alias, host, user, port, and Hermes profile name. They do not contain SSH private keys, API keys, or a stored SSH password.

The app assumes SSH authentication is already handled by your existing macOS and SSH setup.

Network Calls

Hermes Desktop keeps its network surface intentionally small.

In the current implementation, network calls are:

  • SSH connections to the host you explicitly configure
  • an optional GitHub API request to https://api.github.com/repos/dodo-reach/hermes-desktop/releases/latest when checking whether a newer Hermes Desktop version exists

The built-in update check does not update Hermes Agent, does not install anything automatically, and does not send your host, profile, session, file, or Kanban content to GitHub.

What You Can Verify Yourself

If you want to validate the app before trusting it:

  • inspect this repository and build from source with ./scripts/build-macos-app.sh
  • compare the published release checksum with shasum -a 256 HermesDesktop.app.zip
  • verify the installed bundle with codesign --verify --deep --strict /Applications/HermesDesktop.app
  • observe live connections with Little Snitch, LuLu, lsof, or nettop
  • compare this document with the current code, especially the SSH transport, local storage, update check, and packaging scripts

For release-specific details and the limits of those checks, see docs/distribution.md.

Distribution Limitation

The current public app bundle is ad-hoc signed and not notarized by Apple.

That means:

  • macOS can verify bundle integrity after signing
  • the signature does not identify a specific Apple Developer account
  • the release does not carry Apple notarization attestation
  • cautious users may reasonably prefer to build from source instead of trusting the published zip

This limitation is documented so users can make an informed trust decision. It is not hidden, and it should not be described as stronger assurance than it is.

Reporting Security Issues

If you discover a security issue, avoid posting sensitive exploit details in a public issue first.

Use GitHub's private vulnerability reporting flow for this repository if it is available. Otherwise, contact the maintainer privately through GitHub before public disclosure.