Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
# build output
/neverpay
/neverpay-seeddemo
/dist/

# runtime data (sqlite db, uploaded files)
/data/
/data-demo/
/demo-data/
/embed-demo-site/
neverpay.env
# generated wallet recovery sheet — secret, never commit (written into the data dir)
Expand Down
2 changes: 1 addition & 1 deletion DEPLOY.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ receipts, download links, and the embed script.
| `NEVERPAY_ADDR` | Listen address (default `:8080`; Docker `0.0.0.0:8080`) |
| `NEVERPAY_DATA_DIR` | DB + uploaded files + `neverpay.env` (default `./data`) |
| `NEVERPAY_BASE_URL` | Public URL (https or `.onion`); used in links & embed |
| `NEVERPAY_ADMIN_PASSWORD` | Admin password (else a random one is logged on first run) |
| `NEVERPAY_ADMIN_PASSWORD` | Admin password, min 12 chars (else a random 96-bit one is logged on first run) |
| `NEVERPAY_ENV_FILE` | Override the env-file path |
| **Receive keys (watch-only)** | |
| `NEVERPAY_EVM_XPUB` | xpub for ETH + USDC (`m/44'/60'/0'/0`) |
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ buyer picks a coin → unique address + live status → payment confirms

<sub>Default theme — buyers see your store name, logo, and accent color.</sub>

**[See the full guided demo →](demo/)** — every screen of the buyer and seller journeys.

</div>

## Why
Expand Down Expand Up @@ -190,6 +192,7 @@ warranty. Issues and contributions welcome.

| Doc | What's in it |
| --- | --- |
| [demo/](./demo/) | Guided screenshot walkthrough of the buyer and seller journeys; reproduce it locally with `go run ./cmd/seeddemo` |
| [USAGE.md](./USAGE.md) | Zero-to-selling walkthrough: setup wizard, wallets per coin, products, embed, webhooks |
| [DEPLOY.md](./DEPLOY.md) | Deployment, full env reference, Tor/.onion hosting, backups |
| [sdk/](./sdk/) | License-verification SDKs + `NVPAY1` token / `/api/v1` reference |
Expand Down
23 changes: 19 additions & 4 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,21 @@ exploitable bugs until a fix is out.
attributable and addresses aren't reused.

**Admin auth**
- bcrypt password hashing; 256-bit random session tokens; sessions expire (7d)
and are validated server-side on every request.
- bcrypt password hashing (cost 12); 256-bit random session tokens; sessions
expire (7d) and are validated server-side on every request.
- Session cookie is `HttpOnly`, `SameSite=Lax`, and `Secure` when served over
HTTPS (`NEVERPAY_BASE_URL=https://…`).
- `POST /admin/login` is rate-limited (10/min/IP) to blunt brute force; bcrypt
cost further throttles guessing.
- Password policy: a 12-character minimum plus a small common-password blocklist,
enforced by `neverpay setup` and for `NEVERPAY_ADMIN_PASSWORD` on first run. The
auto-generated default password is 96-bit. (An *already-configured* install with
a now-sub-policy `NEVERPAY_ADMIN_PASSWORD` is not bricked on upgrade — it logs a
warning and keeps the existing password.)
- `POST /admin/login` is rate-limited (10/min/IP) **and** brute-force throttled:
consecutive failures from an IP trigger an escalating, auto-expiring cooldown
(capped at 15 min), with a fixed ~750 ms delay on every failed attempt. A correct
password is always accepted — even from a throttled IP — and clears the cooldown,
so the throttle only delays repeated wrong guesses. Active throttling is visible
on `/admin/status`.

**License API (`/api/v1`)**
- Unauthenticated by design — the signed license token *is* the credential, and
Expand Down Expand Up @@ -75,6 +84,12 @@ exploitable bugs until a fix is out.
- **Unbounded activation rows when a key has no seat limit** (`seats = 0`). A
holder of a valid key could create many HWID activations. Bounded by the API
rate limit; set a seat limit for keys that need hard caps.
- **Login rate-limit/throttle is keyed by source IP.** On a shared egress (Tor
exit, CGNAT, VPN — set `NEVERPAY_TRUST_PROXY=1` behind a reverse proxy to get
per-client IPs) the operator and an attacker share one key. The brute-force
throttle never blocks a *correct* password (it's verified before the cooldown
is consulted), but a flood from a shared IP can still hit the coarse 10/min/IP
request limit; a logged-in operator (7-day session) is unaffected.
- **Stale pending orders / expired sessions** accumulate as rows (rejected on
read). Negligible at single-operator scale; prune via DB maintenance if needed.
- **EVM detection reads current balance**, not cumulative received. Safe given
Expand Down
Loading
Loading