mirror of
https://github.com/screentinker/screentinker.git
synced 2026-06-17 03:32:32 -06:00
The 6-digit pairing code is generated client-side, so the server can't raise its entropy without a player change. Instead, harden server-side (no client change): - lib/pair-lockout.js: lock an IP out of POST /api/provision/pair after 5 failed claims (15-min lockout), and expire stale provisioning codes after 15 min so a code is not claimable indefinitely. A successful claim resets the IP. - /pair enforces both. Only an UNKNOWN code (404) counts toward the lockout (a real guess); an EXPIRED code (410) is a legitimate-but-stale code and does NOT count, so a slow bulk rollout from one shared-NAT IP can't lock itself out. getClientIp is Cloudflare-aware (CF-Connecting-IP validated against a trusted edge peer), so the lockout keys on the real per-client IP, never a shared edge. Unit-tested deterministically with injected time, incl. the bulk-rollout-never-locks case. Closes #87 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| admin-users.test.js | ||
| ai-design.test.js | ||
| api.test.js | ||
| apitoken-unit.test.js | ||
| branding.test.js | ||
| config-paths.test.js | ||
| i18n-tokens.test.js | ||
| openapi-contract.test.js | ||
| operator-permissions.test.js | ||
| pair-lockout.test.js | ||
| provisioning.test.js | ||
| schedule-eval.test.js | ||
| schema-check.test.js | ||
| security-fixes.test.js | ||
| tenant-cascade-migration.test.js | ||
| tizen-eval-drift.test.js | ||
| user-deletion.test.js | ||
| widget-render-xss.test.js | ||