Skip to content

Security: nulldoubt/holdawake

Security

SECURITY.md

HoldAwake Security

HoldAwake ships two security compositions from one source tree.

Supported releases

Edition Identifier Security boundary
HoldAwake — App Store Edition online.alkhatib.HoldAwake App Sandbox and public IOKit power assertions
HoldAwake Direct online.alkhatib.HoldAwake.Direct Hardened Runtime, owned caffeinate process, optional privileged helper

Security fixes target the latest published build of each edition. Development, ad-hoc, and unnotarized builds are not public releases.

App Store edition

The Store target is sandboxed and contains no privileged helper, launch daemon, privileged XPC client, helper registration code, or Direct helper identifiers. It creates public IOKit idle-sleep assertions transactionally, retains the exact assertion IDs, and releases only those IDs. Timed expiry uses a monotonic clock.

The Store edition has no network service, updater, telemetry, advertising, account, purchases, or third-party runtime dependencies. Preferences remain in its own UserDefaults container.

Direct session boundary

HoldAwake Direct launches /usr/bin/caffeinate directly with a fixed executable path and constructed arguments. It retains and terminates only its exact child process, never invokes a shell, and never uses killall. A replacement process must launch successfully before the old session is stopped.

Privileged-helper boundary

The optional Direct closed-lid capability uses a non-sandboxed root daemon registered with SMAppService.daemon. It is deliberately narrow:

  • Its XPC interface exposes only query state, begin lease, end lease, restore owned state, and prepare for removal.
  • It accepts no command strings, executable paths, arbitrary argument lists, or caller-provided file paths.
  • Both sides require Team ID PCD2Z975GZ and the exact identifiers online.alkhatib.HoldAwake.Direct and online.alkhatib.HoldAwake.Direct.helper through code-signing requirements. Missing, ad-hoc, or mismatched identities fail closed.
  • The only privileged subprocess is /usr/bin/pmset, invoked directly as either -a disablesleep 1 or -a disablesleep 0; the result is verified with pmset -g.
  • Automated tests replace the helper and process runner with doubles and never mutate real power settings.

The helper refuses to enable lid protection when SleepDisabled is already active without a HoldAwake ownership marker. It does not claim or reset state owned by another administrator or tool.

Persistent pmset risk and recovery

disablesleep is an undocumented, system-wide setting. Unlike an IOKit assertion or caffeinate session, it may persist after an app crash, helper interruption, logout, or restart until a privileged operation resets it. A closed MacBook may therefore remain powered and produce unsafe heat.

Before enabling the setting, the helper atomically creates a root-owned lease marker. It removes the marker only after restoring disablesleep 0 and verifying the result. It attempts restoration on explicit deactivation, timed expiry, normal quit, XPC invalidation, lease expiry, helper termination, and helper relaunch. These controls reduce risk but cannot guarantee cleanup after every OS, storage, hardware, or administrative failure.

If HoldAwake Direct reports that restoration is unconfirmed:

  1. Keep the MacBook open, awake, and well ventilated.
  2. Run sudo pmset -a disablesleep 0 from an administrator account.
  3. Inspect the state with pmset -g.

Do not delete helper files while they own a lease. Use Settings › Activation › Remove Helper, which restores and verifies normal lid sleep before unregistering.

Reporting a vulnerability

Report suspected vulnerabilities privately to mohamad@alkhatib.online with the subject HoldAwake Security. Include:

  • affected edition, version, and macOS build;
  • signing mode and installation source;
  • a concise reproduction sequence and observed impact;
  • relevant logs with personal data and credentials removed; and
  • for Direct helper reports, whether pmset -g shows SleepDisabled active.

Please do not open a public issue for an uncoordinated vulnerability or publish exploit details before a fix is available. You should receive an acknowledgement within seven days; remediation timing depends on severity, reproducibility, and the release path involved.

Out of scope

  • Gatekeeper warnings from locally modified, ad-hoc, or unnotarized builds.
  • Physical access to an unlocked administrator account.
  • Behavior caused by another tool changing pmset after HoldAwake Direct refuses or releases ownership.
  • General macOS, IOKit, /usr/bin/caffeinate, or /usr/bin/pmset vulnerabilities not introduced by HoldAwake.

There aren't any published security advisories