Zcash · Desktop · Self-custody

A Zcash wallet
that keeps quiet.

zbag defaults to the Orchard shielded pool, routes wallet traffic through embedded Tor, and keeps keys in a Rust core. A desktop wallet for macOS, Windows, and Linux, in design preview.

Early access by waitlist
Zone A

The interface

▢ holds no keys

Flutter UI

Renders derived display data. No webview, no npm packages.

Zone B

The core

▣ keys + seed

Rust · librustzcash

librustzcash holds the keys and signs locally, on your own device.

Optional

Keystone

▣ offline

Optional air-gapped signer, spending keys can stay off the internet entirely.

Schematic of zbag's trust boundary. The interface never holds keys, signing happens in the Rust core or on Keystone, on your own device. Not live status.

Refused by design.

Most "desktop" wallets are a web page in a costume. zbag refuses the parts that widen the attack surface.

01npm packages Rejected

Zero npm packages in the interface. No JavaScript dependency tree, so no npm supply chain to poison.

02webview Refused

No embedded browser. The Flutter UI renders its own pixels natively, it is not a website in a window.

03Electron Nope

Not Electron. Your wallet should not ship a whole browser just to draw a balance.

04cloud custody Denied

Keys and seed stay in the Rust core or on your Keystone, on your own device.

THE RECEIPTS

Real npm packages. Recent dates. zbag's interface pulls in none of them.

chalk, debug + 16 more Sep 2025

A maintainer got phished, and about 18 tiny utility packages with roughly 2 billion downloads a week were rigged to rewrite crypto wallet addresses right inside the browser.

Socket.dev
Shai-Hulud Sep 2025

The first self-replicating worm on npm. Using stolen publish tokens, it trojanized more than 500 packages on its own and harvested secrets from every machine it reached.

StepSecurity
react-router, react-start + 40 more May 2026

Attackers hijacked TanStack's own release pipeline and pushed credential-stealing code into 42 Router and Start packages, so it shipped with valid provenance. It ran on install to grab cloud, npm, and crypto wallet secrets. A fresh wave of the same Shai-Hulud worm.

GitHub Advisory
axios 2026

Booby-trapped versions of a package with more than 70 million downloads a week dropped a remote-access trojan, tied to a state-backed group that targets crypto wallets.

Microsoft
event-stream 2018

A volunteer talked his way into maintaining a popular package, then slipped in code aimed at one thing, draining a Bitcoin wallet app. The pattern is not new.

The Register

This removes one large, repeatedly exploited surface, not every risk. zbag's Rust core and Flutter SDK have their own dependencies, which carry their own duty of care. What the interface does not have is an npm dependency tree, or a JavaScript engine for this kind of attack to live in.

WHAT WE TURNED DOWN

A wallet UI has to run on macOS, Windows, and Linux. Here is the honest tradeoff behind each option, including the one we kept.

Cross-platform UI frameworks zbag evaluated, with the verdict and reasoning for each option.
Option Verdict Notes
Electron Too heavy Ships a full Chromium browser plus Node inside every app. Big downloads, heavy memory, and a wide surface you have to keep hardening.
Tauri Inconsistent Lighter, but it borrows each system's own webview, so the same UI renders in a different engine on every platform. On Linux (WebKitGTK) it lags behind with documented rendering and performance bugs, and it can feel like a browser in a frame, not a native app.
Native per-OS Too costly The best feel and the best accessibility, because you use each platform's own toolkit. The catch is a separate UI to build and maintain for every platform, the most effort by far.
Qt Licensing Genuinely polished and cross-platform. But the commercial license is a paid per-seat subscription, and the free path (LGPL or GPL) carries copyleft obligations like shipping Qt's source and allowing relinking. Check qt.io for current terms.
Flutter Our pick One codebase that draws its own pixels with its own engine, so the UI looks and works the same everywhere. No bundled browser, no npm dependency tree, free and open (BSD). The same codebase can ship a mobile build later. Honest caveat: its accessibility is not yet fully at native parity, but the team ships accessibility and semantics improvements in nearly every release, and the gap is closing.

No stack is free of tradeoffs. We picked the one whose weak spot is improving fast, and whose strengths, one consistent and dependency-light UI across desktop and, later, mobile, fit a wallet.

We know these tradeoffs firsthand. zbag's own pre-alpha was built on Tauri, with an embedded Chromium (CEF) renderer and a React UI, the very embedded-browser approach the Flutter rewrite drops. It works, and it is now archived as public source, build from source, no prebuilt binaries, superseded by the beta this page describes.

Tauri alpha · archived source ↗

Privacy, stated plainly.

Each line below is something zbag does by design, in plain language. No absolutes, only what the architecture supports.

  • Shielded by default in the Orchard pool: amount, sender, and recipient are not visible on-chain for shielded sends.
  • Wallet traffic is routed through embedded Arti Tor.
  • If Tor is unavailable, zbag does not fall back to a direct connection.
  • Your ISP sees Tor traffic rather than direct wallet-server requests.
  • The lightwallet server does not receive your direct IP, though it still receives wallet requests.
  • Keys and seed stay in the Rust core.
  • Discreet display controls.
  • Fail-closed behavior.

Built like an instrument.

A Rust core does the sensitive work. The interface works with derived, non-sensitive data, and every automation has a manual lever.

F-01

Shielded by default

zbag keeps funds in the Orchard shielded pool, and an amount is shielded before it can be sent. There is no transparent-send path in the wallet.

Pool · Orchard shielded pool
F-02

Fail-closed Tor

Routed through an embedded Tor client, no system setup. If Tor is unavailable, zbag does not fall back to a direct lightwalletd connection.

Route · Arti, embedded
F-03

Air-gapped signing

Keystone hardware support over animated QR. Your spending keys can live on a device that never touches the internet, signing with PCZT.

Sign · Keystone / PCZT
F-04

Keys stay in Rust

Spending keys never reach the interface. Seed phrases appear only in explicitly permitted flows, not logged or persisted by the UI layer.

Core · librustzcash
F-05

Built-in swap

Built-in swaps route through NEAR Intents and settle as native ZEC on mainnet. zbag treats swap-related transparent exposure as explicit, not hidden.

Swap · NEAR Intents
F-06

Desktop-first

A real desktop application, not a browser tab. The Flutter interface embeds no webview and pulls in no npm packages, which keeps the dependency surface small. macOS, Windows, and Linux.

Build · macOS / Win / Linux

Where your traffic goes.

A schematic of a shielded send, what each party along the path can read, from your own device out to the Zcash chain.

  1. Step 01

    Your own device

    zbag

    Balances, history, and memos in the clear, locally.

  2. Step 02

    Embedded Tor

    Arti

    Carries every wallet request, no fallback to a direct connection.

  3. Step 03

    Lightwallet server

    lightwalletd

    Receives requests over Tor, not your direct IP.

  4. Step 04

    Zcash chain

    Orchard pool

    Amount and parties hidden for shielded sends.

Schematic of a shielded send. Each step notes what that party can read. Not to scale.

What everyone else sees.

Privacy is only real if you can name who is watching and what they get. Here is the read for each observer when a shielded send leaves your own device.

Your ISP
Sees Tor traffic, not direct wallet-server requests.
The lightwallet server
Receives requests over Tor, not your direct IP.
The Zcash chain
Amount and parties hidden for shielded sends.
You
Balances, history, and memos in the clear, locally.
Transparent send Refused

zbag has no transparent-send path. An amount is shielded into the Orchard pool before it can be sent, so every send leaves from the shielded pool. That makes the read above the only case, with no transparent send to put a recipient or amount on-chain in the clear.

Get on the list.

zbag is not public yet, and what you see here is a design preview. Join the waitlist for early builds, release news, and a heads-up before launch.

No third-party email service. Your address lives on our own infrastructure, a single Cloudflare Worker and a small database. We store a SHA-256 of your IP, never the raw address. One message when there is something real to say.
Early accesszbag.app
↳ Self-custodial software · this is not investment advice. We do not sell or share your address.