LightNode is non-custodial: no private key is ever sent to, or stored on, any LightNode server. Everything that touches a key happens locally on the user's machine. This policy covers all the products in this repository:
- the website + desktop app (worker onboarding and dashboards) - detailed below,
- the
lightnode-sdknpm package (encrypted inference, bridge, DAO, worker ops) - keys are caller-supplied, used only to sign locally via viem, never transmitted, - the LightNode Wallet browser extension (
wallet/) - keys are generated and AES-256-GCM-encrypted on-device; see wallet/README.md for its threat model. The wallet has not yet had an external security audit; treat it as a testnet-grade preview until that lands.
In plain terms:
| Item | Leaves your machine? |
|---|---|
| Worker private key | Never. Generated locally, stored locally, signs locally. |
| Keystore password | Never. Generated/entered locally, stored with the key, used locally. |
| Your funding wallet's key | Never. It only reads your address and sends LCAI. |
| Worker public address | Yes - it's public on-chain anyway (it's what you fund and look up). |
| The LCAI funding transaction | Yes - a normal on-chain transfer you approve in your own wallet. |
| Worker stats (jobs, stake, earnings) | Read from the public on-chain subgraph - already public. |
There is no LightNode account, login, or server-side database. Nothing about you is stored on any server.
The worker key is the on-chain identity that stakes, earns, and gets paid. The desktop app generates it locally and uses it to sign worker transactions on your machine - it is never transmitted off-device.
- Generation. On desktop the key is generated natively in the Rust layer; only the public address is returned to the UI. (On web, the toolkit generates it during the copied setup.)
- At rest. It is held in two places, both local: the OS keychain (Keychain /
Credential Manager / Secret Service) and the toolkit's encrypted keystore on disk
(
~/lightchain-worker/keys-<network>- one directory per network, so a key for one network is never overwritten by installing another). On unsigned desktop builds the OS keychain is not reliable across launches, so a localStorage copy is also kept as a fallback. The authoritative copy for signing is the on-disk keystore. - In use. Worker actions (settle, deregister, withdraw) are signed locally. The signing key is preferentially derived from the on-disk keystore using the container's keystore password, and the derived address is verified against the targeted worker before any transaction is sent. This prevents signing one network's action with another network's key.
- Per-network isolation. Secrets are stored strictly per network; a key or password for one network is never returned for another.
The keystore password encrypts the worker key on disk. It is generated (or typed) locally, shown to you once so you can back it up, and stored alongside the key (keychain + the worker container's own environment). The desktop runner passes it to setup/operations through the child process environment, never inside the command text and never in any logged output, and it is stripped from any file that could be committed. Operations recover it from the running container when needed, so the raw key can be decrypted on-device without the password ever being typed into, or sent through, the web layer.
When you create a worker the app shows you the generated password and the worker address (and, on request, the raw key) purely so you can back them up. Only two things ever go further: the worker's public address and the LCAI funding transfer you approve in your wallet. Both are public on-chain data. The key and password do not leave the machine at any point in setup.
The wallet you connect (via Reown AppKit / WalletConnect / injected) is used only to read your address and to send LCAI to the worker address. It never signs worker operations, and its private key never touches LightNode.
The app reads only public, on-chain-derived data from the LightChain workers
subgraph, through server-side /api/* routes (so there is no client CORS exposure
and responses can be briefly CDN-cached). No user data is persisted on any server.
Watchlists and UI preferences live in the browser's local storage only.
The web app sets standard security headers (X-Frame-Options, nosniff,
Referrer-Policy, Permissions-Policy, HSTS) and removes x-powered-by. All
subgraph access is server-side with a timeout and graceful degradation.
Use GitHub's private vulnerability reporting: go to the repository's Security tab -> Report a vulnerability (enabled for this repo). Do not file public issues for sensitive reports. We will acknowledge within 72 hours, investigate, and coordinate a fix and disclosure. Reports affecting the wallet's key handling or the SDK's encryption path are the highest priority.
- LightNode is an independent ecosystem tool, not an official LightChain product.
- It wraps the official
lightchain-worker-toolkitand the worker's Docker image; review that project for the worker runtime's own security model. - The desktop app loads the hosted web UI and grants a minimal, explicitly declared set of native commands (see docs/ARCHITECTURE.md); it does not grant arbitrary shell or filesystem access to the page beyond those commands.