Skip to content

fix: enforce password-reset rate limit and map to 429 - #1336

Merged
thlpkee20-wq merged 6 commits into
RevoraOrg:masterfrom
Ajibola6921:security/issue-1266-security-password-reset-rate-limiter-throws
Oct 24, 2026
Merged

thlpkee20-wq merged 6 commits into
RevoraOrg:masterfrom
Ajibola6921:security/issue-1266-security-password-reset-rate-limiter-throws

Conversation

@Ajibola6921

Copy link
Copy Markdown
Contributor

Overview

This PR fixes the password-reset rate limiter so that a allowed: false result actually rejects the request instead of being swallowed by the surrounding try/catch. It also maps PasswordResetRateLimitedError to a 429 response with a Retry-After header, replaces console.error with the structured logger, and adds regression tests covering both the limited path and the limiter-error policy.

Related Issue

Changes

🔒 Rate-limit enforcement in PasswordResetService.requestReset

  • [MODIFY] src/services/passwordResetService.ts
    • Moved the allowed check outside the try block so a rate-limited result is no longer caught by the fail-open handler.
    • Only the checkRateLimit call is wrapped; limiter infrastructure errors are logged at warn with a metric and follow the documented fail-open policy.
    • Replaced console.error with the structured logger.

🚦 Route mapping

  • [MODIFY] src/routes/passwordReset.ts
    • Maps PasswordResetRateLimitedError to HTTP 429 with a Retry-After header.

🧪 Tests

  • [MODIFY] src/services/passwordResetService.test.ts

    • Regression test: when the limiter returns allowed: false, no token row is inserted and no email is sent (fails on master, passes after the fix).
    • Test covering the documented behaviour when checkRateLimit throws.
  • [MODIFY] src/routes/passwordReset.test.ts

    • Asserts the route returns 429 with a Retry-After header when the service raises PasswordResetRateLimitedError.

Verification Results

npm test -- src/services/passwordResetService.test.ts src/routes/passwordReset.test.ts
✅ All tests passed
Acceptance Criteria Status
When the limiter returns allowed: false, no token row is inserted, no email is sent, and the route returns 429 with Retry-After ✅ Covered by service + route tests
When the limiter throws, the behaviour matches the documented policy and is covered by a test ✅ Fail-open policy logged at warn with metric; test added
Tests in src/services/passwordResetService.test.ts and src/routes/passwordReset.test.ts ✅ Added
A regression test that fails on master (an email is sent while limited) and passes after the fix ✅ Added in service tests
CI stays green ✅ Local test run green

Closes #1266

@drips-wave

drips-wave Bot commented Oct 20, 2026

Copy link
Copy Markdown

@Ajibola6921 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@Ajibola6921
Ajibola6921 force-pushed the security/issue-1266-security-password-reset-rate-limiter-throws branch from e6848f7 to b60ca7d Compare October 22, 2026 11:03
@thlpkee20-wq

Copy link
Copy Markdown
Contributor

Security check: this PR contains malware (the PolinRider campaign) and can't be merged as it is.

Our automated scan flagged these files on your branch:

  • eslint.config.js
  • package.json

These changes are not part of your fix. They hide code that runs automatically on the machine of anyone who opens or installs the project (padded/obfuscated code in config files, node api.js or dist/setup.js in package.json scripts, auto-run .vscode tasks, fake font files, or .gitignore entries for temp_auto_push.bat). When this shows up in a PR it usually means the machine the PR was pushed from is infected and injects it automatically.

Please:

  1. Check your own machine first. From a clean device, rotate your GitHub/npm tokens and SSH keys, move any crypto wallet funds to a new wallet, and review the public PolinRider guidance.
  2. Remove these files and changes from your branch: update it from the latest default branch, which is clean, so the diff only contains your intended change. Don't open the repo in VS Code/Cursor with automatic tasks enabled while doing this.
  3. Push the cleaned branch. The Malware scan check must pass, and then we can review and merge it.

Thanks!

Strips the payload this branch picked up (deleted api.js, unhooked package.json). No functional change to the branch's own work.
@thlpkee20-wq
thlpkee20-wq merged commit 1145ba0 into RevoraOrg:master Oct 24, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

security(password-reset): rate limiter throws inside its own try/catch, so the limit is never enforced (always fails open)

2 participants