This is experimental software and should not be used with real funds.
Warning: This is a work in progress. Only simple transfers are supported. The wallet database is not yet encrypted, IPC provides integrity but not confidentiality, and several security features (DB encryption, interactive password prompts, secrets file support) are planned but not implemented. Review this document carefully before relying on any security property.
┌──────────────────────────────────────────────────────────┐
│ Untrusted zone │ Trusted zone │
│ │ │
│ CLI / TUI process │ keypunkd process │
│ (never holds keys) │ (holds decrypted keys) │
│ │ │
│ paypunkd process │ seed.enc (encrypted at rest) │
│ (never holds keys) │ │
└──────────────────────────┴────────────────────────────────┘
▲ ▲
│ X25519 + Blake2b MAC │
│ (IPC auth) │
└──────────────────────────────┘
The core security boundary is between keypunkd (which holds keys) and everything else. paypunkd and the CLI/TUI never touch key material — they delegate signing to keypunkd via IPC.
Any process that can reach the socket path can complete the X25519 handshake
The handshake establishes a shared MAC key but never verifies who the client is
Access control is entirely via filesystem permissions on the socket path
Risk: On a shared host, any user can connect to the socket. Mitigate by restricting the socket directory permissions or running daemons as separate users.
The bridge HTTP/WebSocket server binds to 0.0.0.0:{port}, not localhost
No TLS, no WebSocket authentication
Any network client can connect and intercept signing requests
Risk: On a networked machine, a remote attacker could connect to the bridge WebSocket and inject forged signing responses
Mitigation: Only use the bridge on a trusted network or behind a firewall. The camera-based QR flow requires localhost or HTTPS for getUserMedia access.
Run keypunkd as a separate system user — Use systemd User= and Group= directives. This provides file/memory isolation even though the code doesn’t enforce it.
Restrict socket permissions — Place Unix sockets in a directory with restricted permissions (e.g., /run/paypunk/ with 0700).
Use the mobile signer for high-value wallets — Air-gapped signing via QR codes eliminates network attack surface.
Don’t use --password on shared systems — Passwords in process arguments are visible to other users via ps.
Encrypt the wallet database — Until DB encryption is implemented, consider full-disk encryption (LUKS) for the data directory.
Keep keypunkd off the network — keypunkd only needs a Unix socket, not network access. Firewall it if possible.