Skip to content

Wallet & Key Custody (Security View)

The security-facing summary of Ghast's wallet model. For the user-facing setup flow, see Web3: Wallet & Key Custody.

Key statement

Ghast does not custody your wallet keys. The wallet private key sits encrypted on your machine. Decryption is in-memory and ephemeral. The Ghast backend, the on-chain layer, and any remote service all see only what your wallet signs.

Storage

~/<userData>/profiles/<profileId>/
└── wallet.json   ← AES-256-GCM ciphertext of the wallet private key

The encryption key (the "vault key") is:

  • Generated by the Ghast backend on each sign-in.
  • Returned over TLS to the desktop client.
  • Held only in process memory.
  • Never written to disk.
  • Wiped on profile switch, sign-out, or app quit.

Cold-booting the machine and not signing in → no vault key → wallet.json is unreadable.

Signing flow

For every signing operation (Ledger deposit, provider funding, TEE acknowledgement, API token, sync pointer):

  1. Caller asks the wallet keystore for the wallet.
  2. Keystore decrypts wallet.json with the in-memory vault key.
  3. A short-lived ethers.Wallet instance is constructed.
  4. The signature is computed.
  5. The wallet object is released.

The decrypted key never lands on disk, never appears in logs, and never lives beyond the operation.

What the agent can and cannot do with your wallet

The agent runtime (skills, tools, MCP, Computer Use) cannot call loadWalletPrivateKey(). That capability is reserved for the trusted main-process modules (zerog-compute/, services/data-sync-service.ts, etc.). A malicious skill or compromised MCP server cannot extract your key.

The agent can ask you to authorise a signing action — the relevant flows surface confirmation cards in the UI before submitting. You can decline.

Mnemonic handling

The BIP-39 mnemonic (or imported equivalent) is:

  • Shown exactly once at creation. You confirm by typing it back.
  • Not re-displayed in plaintext anywhere in the UI afterwards.
  • Stored only as the derived private key in wallet.json. The mnemonic itself is not retained.

This means: lose the mnemonic + lose the device → wallet unrecoverable. Ghast cannot recover keys for you.

Profile isolation

AspectEffect
One profile → one wallet addressMultiple profiles → multiple independent wallets
Switching profilesWipes the previous vault key from memory; backend issues a new vault key for the new profile
Cross-profile readsNot possible — each profile has its own vault key, its own database

What this stack does not protect against

The honest threat-model boundaries:

  • Malware with full disk access while you're signed in. With both wallet.json and the in-memory vault key, an attacker can decrypt the wallet.
  • A compromised macOS user account. OS-level isolation is out of scope; Ghast does not add another sandbox.
  • A leaked mnemonic. If you wrote the mnemonic somewhere unsafe, that's outside Ghast's control.

For these, mitigations are at the OS level: filesystem encryption, locked devices, password-managed mnemonic storage.

Auditing what Ghast signs

Every chain transaction:

  • Surfaces a confirmation card in the desktop UI before being submitted.
  • Lands on-chain at evmrpc.0g.ai — you can read your own transaction history.
  • For 0G Storage, the pointer registry contract is also queryable.

You can independently verify everything Ghast signs on your behalf.