Foundation Inkfire Login 2.0.28
Fix: the branded reset-password form never actually reset the password
Found during a maintenance audit. This is more serious than 2.0.27 and has been present since 2.0.11 (13 Jan 2026).
Symptom
A user requests a password reset, receives the email, clicks the link, sets a new password — and is bounced back to Lost password with an invalidkey error. Their password is unchanged. From the user's side it simply looks like password reset is broken.
Cause
wp-login.php does not keep the reset key in the URL. On action=rp it moves the key into the wp-resetpass-<COOKIEHASH> cookie, strips it from the URL, and redirects to action=resetpass.
The branded form was still reading the key from the query string:
$rp_key = ifls_sanitize_request('key'); // empty by the time the form rendersso the hidden rp_key field posted an empty string, and core's check failed:
if ( isset( $_POST['pass1'] ) && ! hash_equals( $rp_key, $_POST['rp_key'] ) ) {
$user = false; // -> lostpassword&error=invalidkey
}Fix
Read the login/key pair from the cookie exactly as core does, falling back to the request only for the initial action=rp render before the cookie exists. $rp_key is passed through unaltered because it is compared with hash_equals().
Verified
On a live site, before vs after:
| 2.0.27 | 2.0.28 | |
|---|---|---|
rp_key in rendered form |
(empty) | populated from cookie |
| Submitting the form | 302 → error=invalidkey |
200 |
| Password actually changed | no | yes |
Security regressions checked — both still correctly rejected, password left intact:
- forged key with no reset cookie →
invalidkey - tampered key with a valid reset cookie →
invalidkey
The full 12-scenario CSRF matrix introduced in 2.0.27 still passes unchanged.
Upgrading
Automatic via the bundled updater.