DocsKeys and security

Trust

Keys and security

Your keys are encrypted on your machine and unlocked only inside the running process. This page lists what is stored, what talks to the network, and what zeroterm cannot protect you from.

The short version

  • There is no zeroterm server, account or telemetry. Nobody but you sees your keys, your passphrase or your trades.
  • Keys are encrypted at rest. They are decrypted into memory only after you unlock, and wiped when you lock or quit.
  • The only things that leave your machine are signed transactions, to the routes you turned on, and read requests for prices and coin data.
  • The code is short enough to read. Start with vault.ts and server.ts.

The vault

Your wallet keys live in ~/.zeroterm/vault.json.

  • Your passphrase (at least 10 characters) is turned into a 256-bit key with scrypt (N = 2¹⁵, r = 8, p = 1) and a random 16-byte salt.
  • Each wallet's secret key is encrypted with that key using AES-256-GCM, with its own random 12-byte nonce. The file also holds an encrypted check value, so a wrong passphrase is refused instead of producing garbage.
  • The file and the ~/.zeroterm folder are readable only by you (modes 600 and 700). Writes go through a temporary file, so a crash never leaves half a vault.
  • Unlocking (u) decrypts the keys into the process's memory. Locking (L) or quitting overwrites them with zeros.

The passphrase cannot be recovered. With the vault file and the passphrase, your keys can be opened on any machine running zeroterm; with only one of the two, they cannot.

Backups

Copy ~/.zeroterm/vault.json somewhere safe, and keep the passphrase separately. That pair is the whole backup. You can also write down each wallet's key: W then k shows it.

Showing a key

The wallet menu can show a wallet's secret key (W then k). zeroterm asks for the passphrase again first, even when the vault is unlocked, so a terminal left open cannot hand a key to whoever sits down at it. The key is decrypted for that one display and cleared from the screen when you close it. In browser mode the page receives the key only after the passphrase is checked, over the local token-protected connection.

The local server

The full-screen terminal opens no port at all: the trading engine runs inside the same process, driven by your keyboard.

Browser mode (--web) starts a small server so the browser tab can reach that engine:

  • It listens on 127.0.0.1 only. Other machines on your network cannot reach it.
  • It refuses any request whose Host is not 127.0.0.1 or localhost on its own port, and any Origin other than its own page. A website you visit cannot drive it.
  • Every API call and the websocket need a 24-byte token made fresh at each start. It is in the address zeroterm prints, after the #, which browsers never send to a server.
  • Secrets in your settings (RPC keys, the Sender key, the Jito UUID, the Nozomi and Jupiter keys) reach the page only redacted.

What talks to the network

zeroterm --hosts prints every host zeroterm talks to with your current settings, and why. With the default settings:

api.mainnet-beta.solana.com              RPC: reads and trades
sender.helius-rpc.com                    Helius Sender: trades
ny.mainnet.block-engine.jito.wtf         Jito: trades
frankfurt.mainnet.block-engine.jito.wtf  Jito: trades
tokyo.mainnet.block-engine.jito.wtf      Jito: trades
pumpportal.fun                           new coins (public stream)
api.geckoterminal.com                    hot list and finding a coin's pool (public API)
api.jup.ag                               Jupiter: routes for coins zeroterm does not trade directly
ipfs.filebase.io                         coin images
4everland.io                             coin images
ipfs.io                                  coin images
gateway.pinata.cloud                     coin images

…and each coin's own metadata link. Nothing else: no account, no telemetry, no update check. Keys and passphrases go to none of them.

What each one learns:

  • Your RPC sees your public address, the coins you look at and your signed trades, as any RPC you use would. Use one you trust.
  • Landing routes (Helius Sender, Jito, Nozomi, yours) receive signed transactions, which are public the moment they land anyway.
  • Jupiter receives the two mints, the amount and your public address, only for coins it routes.
  • PumpPortal, GeckoTerminal and the IPFS gateways receive requests for public data, with no wallet attached.

Installing safely

  • zeroterm is built from source on your machine, so the code you run is the code you can read.
  • pnpm 10 runs no dependency's install script, and every dependency is pinned in pnpm-lock.yaml.
  • A dry run (d) simulates the exact order on mainnet with nothing unlocked and nothing signed.

What zeroterm cannot protect you from

  • Malware on your computer. A keylogger can read your passphrase as you type it, and a program running as you can read memory while the vault is unlocked. Lock the vault (L) when you step away.
  • A lost passphrase. There is no recovery.
  • The coin itself. zeroterm executes the trade you sign; it does not judge the coin. Most memecoins go to zero.
  • Your RPC's view. Your RPC provider can see your address and your trades.

Reporting a vulnerability

Please report it privately, as described in SECURITY.md, rather than in a public issue.

↑ ↓ to move · ⏎ to open