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 keyThe 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):
- Caller asks the wallet keystore for the wallet.
- Keystore decrypts
wallet.jsonwith the in-memory vault key. - A short-lived
ethers.Walletinstance is constructed. - The signature is computed.
- 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
| Aspect | Effect |
|---|---|
| One profile → one wallet address | Multiple profiles → multiple independent wallets |
| Switching profiles | Wipes the previous vault key from memory; backend issues a new vault key for the new profile |
| Cross-profile reads | Not 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.jsonand 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.
