SOURCE ↗

Security

This page explains how Nani protects your wallet — what's stored where, who can read it, and what happens when you sign something.

Where the key lives

Your private key sits in the modern macOS Keychain (Apple's Data Protection store) under the service com.thresholdstudio.nani.wallet. Two protections apply:

  • Available only when your Mac is unlocked. macOS keeps the encryption key for the item in memory only while you're logged in.
  • Bound to your current Touch ID enrollment. Reading the key requires Touch ID against the fingerprint set you have right now. If anyone adds or removes a fingerprint, the key becomes unreadable until you re-store it. This stops the "stolen Mac, attacker re-enrolls Touch ID" attack.

On Macs without Touch ID (some Intel Macs, VMs), Nani encrypts the key with a password you set. The encryption is AES-256-GCM with a key derived through PBKDF2-HMAC-SHA256 at 600,000 rounds — slow enough to make brute-force impractical.

What happens when you sign

Every signature, whether from the wallet UI or proposed by the AI, runs the same five-step pipeline:

  1. Policy check. Nani checks the transaction against your configured limits — value cap, hourly cap, gas-price ceiling. If it fails, you see a clear "rejected by policy" message and no Touch ID prompt fires.
  2. Touch ID. macOS shows the standard biometric prompt. If you cancel, the signature is aborted.
  3. Read the key from the Keychain using your authenticated session.
  4. Sign the transaction with secp256k1 (the curve Ethereum uses).
  5. Wipe the key from memory immediately, then broadcast.

The key is in memory for less than a millisecond, only inside the wallet's signing function, and only after you authenticated.

Policy limits

Nani lets you cap how much can move in any one transaction or any hour. AI-proposed transfers have lower default limits than manual ones — the assistant is useful but it's also a language model, and language models can be tricked.

LimitManual defaultAI default
Max value per transaction1 ETH0.1 ETH
Max value per hour5 ETH0.5 ETH
Max transactions per hour1010
Max gas price500 gwei500 gwei

Tune these in Settings → Policy. The settings and rate-limit history are stored locally with an integrity tag (HMAC) so a process running on your Mac can't quietly edit them to lift the cap.

How the AI is sandboxed

The assistant's tools run in a hidden in-app browser (a WKWebView). The browser is a separate macOS process with strict rules:

  • It can only run the bundled tool script — no remote code, ever.
  • It can only talk to a fixed list of HTTPS endpoints — ENS resolvers, DEX aggregators, block explorers, price APIs.
  • It cannot read your filesystem or your other apps.
  • It receives your wallet address but not your key. There's no path from the tool layer to the Keychain.

The assistant proposes transactions; the wallet executes them. That separation is the whole point of letting an AI near your money safely.

Network

Here's everything Nani talks to:

  • The chain. Whatever RPC you've configured per network — by default these are public endpoints like publicnode.com.
  • Your AI provider, if any. Nothing for MLX (local). OpenRouter or your Ollama server if you've selected one.
  • Tool endpoints. A fixed allowlist used by agentek when the assistant calls a tool.
  • HuggingFace — once, when you first download the local AI model.
  • nani.ooo/update.json — once on launch, to check for a new version.

That's the full network surface. There is no telemetry, no analytics, no error reporter, no remote config.

Updates

Updates are signed with an Ed25519 key that lives offline. The matching public key ships in Nani's Info.plist. Before installing, the app verifies both the file size and the signature using Apple's CryptoKit — if either check fails, the update is discarded and your installed app is untouched.

The install script runs as your user account, with no XPC service and no privilege escalation. Full details in Updates.

Best practices

A self-custody wallet is a sharp tool. Two habits cover most of the risk:

  • Write down your recovery phrase on paper and put it somewhere only you can reach. That's the one backup that matters.
  • Read what you sign. Whether the wallet UI or the AI proposed it, the confirmation screen shows the parsed transaction. If something looks off — wrong recipient, surprising amount, unfamiliar contract — cancel.

That's it. Touch ID and the policy engine handle the rest.

Reporting a vulnerability

Found a security issue? Open a private security advisory at github.com/NaniDAO/nani-macos/security/advisories. Wallet-impacting bugs are critical — we aim to respond within 48 hours.