fix(security): close four middleware gaps around the API edge

- maintenance mode classified paths case-sensitively while Express routes
  case-insensitively, so /API/... walked past the gate
- the general rate limiter skipped anyone holding any verified JWT; a
  gallery token is minted for free on password-less galleries and slideshow
  links, so that was an unlimited budget for every /api route. Only admin
  sessions skip now
- ?admin_preview=1 trusted a verified signature alone; it now applies the
  same revocation, restore-cutoff, deactivation and password-change checks
  adminAuth does, and reveal-mode reads the verified flag instead of
  re-decoding the token
- the 50mb JSON limit is scoped to /api/admin and /api/v1; everything else
  gets 2mb, so an unauthenticated body can no longer stall JSON.parse
- the CSRF Content-Type gate accepted multipart from any origin; cross-site
  form posts are now rejected via Sec-Fetch-Site / Origin, with a Host match
  fallback for same-origin installs that leave FRONTEND_URL unset
This commit is contained in:
Paul Nothaft
2026-09-03 10:51:53 +02:00
parent 063977d97d
commit 839bf4e464
8 changed files with 249 additions and 34 deletions
+7 -2
View File
@@ -115,8 +115,13 @@ function isAuthenticated(req) {
return false;
}
// Valid token found - check type
req.tokenType = decoded.type; // 'admin' or 'gallery'
// Only an admin session earns the skip. A gallery token is minted for
// free on password-less galleries and slideshow links, so treating it as
// "authenticated" handed anyone an unlimited budget on every /api route.
if (decoded.type !== 'admin') {
return false;
}
req.tokenType = decoded.type;
req.tokenPayload = decoded;
return true;