Security
Trust model
- Server seed (
SERVER_SEED) is the root of HMAC auth (capabilities + admin proofs). Compromise = full admin minting.
- Client identity seed under
~/.config/peardata/identity.json identifies the peer across reconnects. Protect it if you bind capabilities to peerId.
- HyperDHT provides mutual authentication of keypairs on the secret stream. RPC still needs application AuthZ (roles).
- UI process can hold an admin seed in memory when the user pastes it — treat the desktop machine as trusted for that session.
Auth paths
- Admin proof — client proves knowledge of seed-derived MAC key without sending the seed (
createAdminProof / verifyAdminProof).
- Capability — server-signed grant with role, optional expiry, optional peer binding, JTI spend tracking.
- Registered peer — after a successful grant, reconnects may use the stored role without replaying a spent JTI (see
redeemCapability / peer policy).
- Admin keys env —
PEARDATA_ADMIN_KEYS forces admin for listed peer public keys.
- Revocation —
revokePeer drops live sessions and blocks future dials.
- Allowlist — when
PEARDATA_ALLOWLIST is non-empty, unknown peers are rejected.
Secure defaults
| Default |
Value |
| Unknown peer role |
viewer |
| Open admin |
off |
| Capability forever |
yes unless ttlMs set |
| Rate limit |
120 RPC / minute / peer |
| Audit |
mutating methods + handshake failures |
| Identity file mode |
0600 |
| Data directory |
local ./data (not committed) |
REST API exposure
- Default bind is localhost only (
127.0.0.1:18888).
- REST is intentionally open on that bind (local-agent style) — do not set
PEARDATA_REST_HOST=0.0.0.0 without a firewall, reverse proxy, or Holesail tunnel.
- Prefer P2P + roles for remote multi-operator access; use REST for local scrapers/Grafana.
Production checklist
Threat notes
| Threat |
Mitigation |
| Stolen invite |
Short TTL; peer-bound capabilities; revoke JTI / peer |
| Stolen client identity |
Revoke peer id; re-issue invites |
Stolen SERVER_SEED |
Rotate keypair; all grants invalid; re-onboard clients |
| RPC spam |
Rate limiter (PEARDATA_RATE_LIMIT_RPM) |
| Confused deputy role |
Server never trusts client-supplied role field |
| Log leakage |
Logger never prints seeds/tokens |
| Rogue desktop |
OS user access = ability to paste seed; use invites on shared machines |
| Supply chain |
Pin deps; review npm audit; CI from trusted runners |
Crypto details
| Item |
Algorithm / format |
| DHT identity |
Ed25519 via HyperDHT keyPair(seed) |
| MAC key |
HKDF-SHA256(seed, salt=peardata-hmac-v1, info=capability) → 32 bytes |
| Capability MAC |
HMAC-SHA256(macKey, canonical JSON payload) |
| Admin proof |
HMAC-SHA256(macKey, peardata-admin-v1 ‖ nonce ‖ peerId ‖ serverPk) |
| Invite envelope |
pd1. + base64url(JSON) |
Implementation: shared/crypto-auth.js.
Canonical capability payload fields
v, role, peerId, exp, jti, iat — ordered JSON before MAC.
Operational security
| Artifact |
Sensitivity |
Handling |
.env |
Critical |
Never commit; backup offline |
data/peer-policy.json |
High |
Contains roles & JTIs |
data/audit.log |
Medium |
Peer activity metadata; readable via Logs/audit (admin) |
Host journal (PEARDATA_JOURNAL) |
High |
May include secrets from other units; admin-only; on by default (disable with =0) |
Docker socket (PEARDATA_DOCKER) |
High |
Container inventory/names/stats; installer adds peardata to docker when detected |
data/retention.json |
Medium |
Retention / prune policy (admin-writable over P2P) |
identity.json |
High for that user |
Per-machine client secret |
| Release tarballs |
Low |
Source only; no secrets |
Incident response (seed leak)
- Stop accepting connections on the compromised key (shutdown / firewall).
- Generate new
SERVER_SEED on a clean host (new public key).
- Deploy new server; do not reuse old seed.
- Re-issue invites to operators; notify clients of new public key.
- Review
audit.log for abuse window.
Related