fix(security): rate-limit the password-change endpoints per IP too

POST /api/auth/admin/change-password and POST /api/customer/profile/password
both verify the current password before replacing it, which makes them a
credential check an attacker holding a hijacked session can drive at will:
the session's own JWT skips the general limiter as authenticated, and they
were not in the auth gate's table. Both join it. Only failures count, so
the one change a user legitimately makes costs nothing.
This commit is contained in:
Paul Nothaft
2026-09-02 09:43:11 +02:00
parent 4515632300
commit 5a0c9f53b0
2 changed files with 15 additions and 3 deletions
@@ -58,6 +58,13 @@ const CREDENTIAL_ENDPOINTS = [
// Customer portal password, and the reset that replaces it.
{ method: 'POST', path: /^\/api\/customer\/auth\/login\/?$/i },
{ method: 'POST', path: /^\/api\/customer\/auth\/password-reset\/?$/i },
// Password changes verify the CURRENT password first, so they are a
// credential check too — one an attacker holding a hijacked session can
// drive, and one the general limiter never sees because the session's own
// JWT skips it as authenticated. Only failed attempts count here, so the
// one legitimate change a user makes costs nothing.
{ method: 'POST', path: /^\/api\/auth\/admin\/change-password\/?$/i },
{ method: 'POST', path: /^\/api\/customer\/profile\/password\/?$/i },
];
/**