Skip to content

Security: corbinallison/paysafe-node

Security

SECURITY.md

PaySafe-Node security posture (v0.1 trial)

Maps the marketplace plan's §8 security architecture to what this MVP actually implements. Honesty over marketing — this is a friends-and-family trial build.

Implemented now

Plan principle Implementation
Hosts dial out, never listen (§3) Agent opens one outbound WSS to the relay + loopback to Ollama. Zero inbound ports, no port forwarding, host IPs never exposed to renters.
Curated models only (§8.1) Relay enforces ALLOWED_MODELS; agent re-enforces locally (defense in depth). No arbitrary code, no renter-supplied URLs ever fetched.
Concurrency-aware routing (§3) Slots advertised in heartbeats; relay routes least-loaded-first; agent rejects over-slot jobs locally.
Canary probes (§8.2) Hardware-independent known-answer probes (string reversal, case transforms, char counts) to idle nodes every ~10 min, disguised as normal jobs.
No single-mismatch slashing (§8.2) Quarantine only after 3 consecutive canary failures — float non-determinism across GPUs never punishes an honest host.
Hardware fingerprinting (§8.3) GPU name/UUID/VRAM/driver captured at registration for bait-and-switch detection.
Invite-only registration (§8.3) Single-use invite codes minted by admin — Sybil resistance for the trial (stakes come later).
Replay protection (§8.4) Handled by the official x402 facilitator (verify/settle) via @x402/express — payment authorizations are single-use at the facilitator layer.
Canonical USDC only (§8.4) The x402 resource server resolves the canonical USDC contract per network from its registry; lookalike assets never accepted.
Ledger-first payouts (§3) Hosts credited 80% in the relay ledger — only AFTER x402 settlement succeeds (post-settlement hook), never on unsettled responses; weekly batch payouts; you hold float.
Pay-on-pass settlement (§8.4) /v1/task/* outputs are validated deterministically (schema/label/word-bound checks); the payment middleware settles only on <400 responses, so a failed task (422) is never charged. Renter-supplied JSON schemas are bounded: 8KB, depth ≤ 8, keyword allowlist (no pattern/$ref — no ReDoS or recursion surface). Validators are pure functions — no LLM judge, so no injection surface there.
Audit log hash-chaining (§8.6) Money events (settlements, payouts) land in an append-only JSONL chain (prev_hash/entry_hash, ported from PaySafe's auditlog.ts); GET /v1/audit/verify replays the chain; payouts zero the ledger only through the audited POST /v1/payouts.
No prompt retention (§8.2/§8.7) Prompts/outputs stream through memory on both relay and agent; job records and logs carry sizes/timings/outcomes only.
Credential hygiene (§8.6) Node tokens stored only as SHA-256 hashes on the relay; per-node revocation = flip quarantined. Admin endpoints use constant-time key comparison.
Payload caps (§8.1) 256KB request cap on relay and agent; generation options sanitized to an allowlist (temperature/num_predict/seed).
Supply-chain check (§8.6) Installer verifies the agent zip's SHA-256 against a pinned release hash.
PaySafe integration (§8.5) Optional payer reputation screening via PaySafe /v1/reputation/:address before serving paid jobs; advisory, never fails closed.

Deliberately deferred (and why that's OK for a trial)

Plan principle Status
Container sandboxing (gVisor/signed images) Ollama runs models natively — model weights from the official Ollama registry are data, not code, so the practical risk at this stage is low. Container isolation returns when the catalog grows beyond Ollama's registry.
Hosts can read prompts (§8.2) True here as in the plan. Trial rule: no sensitive prompts; renters are told. TEE tier is the long-term answer.
Stake-to-earn (§8.3) Invite-only replaces stakes while hosts are friends.
Output verification sampling (§8.2) Canaries + task validators at MVP; duplicate-job sampling needs ≥2 nodes per model — enable once supply exists.
Bazaar discovery (§8.4) Code uses the official @x402/express + CDP stack (mainnet-ready; see docs/MAINNET-RUNBOOK.md for the flip), but the Bazaar declareDiscoveryExtension metadata isn't declared yet — add it once the task API shape has survived first paying customers.
Wallet segregation / Safe multisig (§8.4) Operational, not code: runbook step 2 — PAY_TO must be a fresh hot wallet that sweeps to a Safe before the mainnet flip.

Trial threat model, plainly

Friends running nodes are semi-trusted; the real exposure is (1) a stranger getting a relay URL and hammering free dev-mode inference — mitigated by keeping the relay URL private during the trial and the invite gate on registration; and (2) a compromised friend PC serving garbage — mitigated by canaries + quarantine. Neither can touch funds: no keys exist anywhere in this system (PaySafe philosophy: non-custodial by design).

There aren't any published security advisories