fix(security): rate-limit the whole /api/provision pairing surface (#88)
Some checks are pending
CI / Unit tests (node --test) (push) Waiting to run
CI / Android unit tests (Kotlin schedule evaluator vectors) (push) Waiting to run
CI / Boot smoke + version check (push) Waiting to run

POST /api/provision (the routes/provisioning.js router endpoint) pairs a device
by pairing_code with no rate limit - the limit at server.js:287 was bound only to
the /api/provision/pair override. An authenticated user could brute-force 6-digit
pairing codes against the bare endpoint to claim devices in the unclaimed pool.
Bind the rate limit to the /api/provision mount so it covers both pairing paths.

Verified: 6 rapid POSTs to /api/provision now 429 on the 6th (was unlimited);
/api/provision/pair still 429s on the 6th.

Closes #88

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
ScreenTinker 2026-06-12 10:38:32 -05:00 committed by screentinker
parent 11e339dd89
commit 300d331562

View file

@ -283,8 +283,12 @@ app.use('/api/auth/register', rateLimit(60000, 5)); // 5 registrations per minut
// path prefix first, so this fires before /api/auth catches the request.
app.use('/api/auth/users', rateLimit(60000, 20));
app.use('/api/auth', require('./routes/auth'));
// Rate limit pairing to prevent brute force (5 attempts per minute per IP)
app.use('/api/provision/pair', rateLimit(60000, 5));
// Rate limit pairing to prevent brute force (5 attempts per minute per IP).
// #88: bind this to the whole /api/provision surface, not just /pair - the bare
// POST /api/provision (routes/provisioning.js) is a second pairing endpoint that
// was unthrottled, letting an authed user brute-force pairing codes. /api/provision
// matches both /api/provision and /api/provision/pair.
app.use('/api/provision', rateLimit(60000, 5));
// Rate limit expensive operations
app.use('/api/status/export', rateLimit(60000, 5)); // 5 exports per minute
app.use('/api/status/import', rateLimit(60000, 3)); // 3 imports per minute