Skip to content

Elevation and Security

NK edited this page Aug 14, 2026 · 1 revision

Elevation and security

Reading a physical disk needs root. GHOST RECOVER is designed so the unprivileged engine stays unprivileged: it never runs with more rights than the user, and the privileged instance is gated behind a fresh session token.

Unlock disk access

When a disk is locked, the interface offers to unlock it:

  1. The engine reports its options via /api/privileges (pkexec, sudo, sudo_nopasswd, and which is preferred).
  2. You pick a method; the engine launches a privileged copy of itself.
  3. The privileged instance claims the port from the running one (SO_REUSEPORT + a takeover token) and generates a fresh session token.
  4. The browser reconnects to the same page — now with full disk access.

Method notes:

  • pkexec (preferred) — your desktop's own authentication dialog; the password never passes through this program.
  • sudo — fallback where polkit is unavailable; the password is used once and never stored.
  • sudo-nopasswd — offered when the user has passwordless sudo.

The privileged engine stays running after the browser closes, so the token file (kept in a 0700 runtime directory, e.g. /run/user/<uid>/ghost-recover-<uid>/) is the only key to the API. Restart your session with sudo ghost_recover if you want it gone.

Session token

A root-privileged engine demands the session token on every /api request:

  • Browser JS sends it as the X-Ghost-Token header.
  • Media tags (<img>, <video>, <audio>), inline previews and downloads cannot set headers, so /api/content also accepts ?tok=…; the UI appends it automatically.
  • The launcher hands the browser the URL as http://localhost:3030/#tok=…; the UI stores it in sessionStorage and uses it for the rest of the session.

Without this, any local process — not just the browser — could drive the root engine to read or write files it could not reach itself.

Network posture

  • By default the engine binds 127.0.0.1 and rejects any request whose Host or Origin is not loopback — cross-site requests (including null origins from sandboxed iframes and data:/file: pages) are refused, and DNS-rebinding attacks fail because a rebinding attacker's requests carry their own domain as Host.
  • Plain clients (curl, the engine's own handover IPC) send no Origin and remain unaffected.
  • --allow-remote opts into wide-open LAN access on purpose (Access-Control-Allow-Origin: *).

Write protection

  • The engine is read-only by default: --allow-writes must be passed explicitly to permit repair operations to modify a device.
  • Recovered data is never written back onto the source disk — only into the output root.
  • The output root is configurable (--output DIR, $GHOST_OUTPUT, or ~/ghost-recover-output), and /api/file / /api/extract paths are confined to it.

Content security

The HTML page is served with a strict Content-Security-Policy (script-src 'self' 'unsafe-inline', font-src 'self', object-src 'none', base-uri 'none', form-action 'none'), so all scripts and fonts come from the engine itself and PDFs previewed in iframes are framed only by the page that owns them.

Clone this wiki locally