Skip to content

Security: password-reset token retained in the change-password page URL (SUF-05) #331

Description

@devondragon

Summary

After validating a password-reset token on the initial GET, the controller redirects to the change-password page with the raw token retained as a query-string parameter. The token is not consumed at this GET, so it stays valid (default 24h) while sitting in a user-visible URL.

Severity: Medium

Affected code

  • src/main/java/com/digitalsanctuary/spring/user/controller/UserActionController.java:79showChangePasswordPage; line ~92 re-adds the raw token to the redirect model, producing Location: /user/forgot-password-change.html?token=<token>.
  • src/main/java/com/digitalsanctuary/spring/user/service/UserService.java:979validatePasswordResetToken (GET) validates/expiry-checks only; it does not consume a valid token.
  • src/main/java/com/digitalsanctuary/spring/user/service/UserService.java:688validateAndConsumePasswordResetToken (atomic single-use consume) runs only later on the POST /user/savePassword.

Details

Because the token is placed into a redirect (redirect: → 302 with a Location query parameter), it lands in the address bar, browser history, and the Referer sent when the change page loads sub-resources. No Referrer-Policy or Cache-Control headers are set on these pages. Since the GET does not consume the token, a leaked-but-unused token remains replayable until the password is submitted or the token expires (passwordResetTokenValidityMinutes default 1440).

Note: the emailed reset link itself already carries the token in a URL, so this redirect propagates token-in-URL rather than introducing it — but it does add a second URL and the associated Referer/history/analytics exposure (CWE-598).

Recommended fix

  • On the first GET, consume/exchange the token for short-lived server-side one-purpose state (flash/session attribute) and redirect (303 See Other) to a clean URL with no token.
  • Add Referrer-Policy: no-referrer and Cache-Control: no-store on the reset pages.
  • UserActionControllerTest currently asserts the token-in-URL behavior (redirectedUrl(... ?token=...)); update alongside the fix.

Identified during a code-first security assessment of the current main branch.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingsecurity

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions