Skip to content

Stop get_password_reset_key() from firing profile_update#12651

Open
irozum wants to merge 1 commit into
WordPress:trunkfrom
irozum:fix/62996-register-new-user-profile-update-hook
Open

Stop get_password_reset_key() from firing profile_update#12651
irozum wants to merge 1 commit into
WordPress:trunkfrom
irozum:fix/62996-register-new-user-profile-update-hook

Conversation

@irozum

@irozum irozum commented Jul 23, 2026

Copy link
Copy Markdown

register_new_user() and the wp-login.php?action=lostpassword flow both call get_password_reset_key() to generate an account-activation / password-reset link. That function saved the internal user_activation_key column via wp_update_user(), which routes through wp_insert_user() and unconditionally fires profile_update — even though nothing about the user's profile actually changed. Since [45714] (#45746), this means every brand-new account registration also fires profile_update, which breaks the long-standing distinction between user_register (a new account) and profile_update (an existing user editing their own profile) that plugins such as BuddyPress, bbPress, and Easy Digital Downloads rely on for user-facing profile-update integrations.

This updates get_password_reset_key() to write user_activation_key directly via $wpdb->update() plus clean_user_cache(), the same narrow pattern wp_set_password() already uses for its own single-column write, instead of going through the full wp_insert_user() path. This preserves the cache-consistency fix from [45714] while no longer firing profile_update (or any of the meta/role writes wp_insert_user() would otherwise perform) for what is only an internal key rotation.

Adds two regression tests to tests/phpunit/tests/user.php: one asserting get_password_reset_key() no longer fires profile_update (while still persisting user_activation_key), and one asserting register_new_user() still fires user_register exactly once but no longer fires profile_update. Both fail on current trunk and pass with this fix. Full user (1343 tests) and auth (143 tests) PHPUnit groups pass with no regressions; PHPCS and PHPStan are clean.

Trac ticket: https://core.trac.wordpress.org/ticket/62996

Use of AI Tools

AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Sonnet 5
Used for: Root cause analysis, implementation, test coverage, and verification. Reviewed and directed by me throughout.


This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.

Copilot AI review requested due to automatic review settings July 23, 2026 02:09
@github-actions

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Core Committers: Use this line as a base for the props when committing in SVN:

Props irozum.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR changes how WordPress persists user_activation_key during password reset / activation key generation so that internal key rotation no longer routes through wp_update_user()/wp_insert_user() and unintentionally fires profile_update for non-profile changes (notably during new user registration flows).

Changes:

  • Update get_password_reset_key() to write user_activation_key directly via $wpdb->update() and clear user cache.
  • Add PHPUnit regression tests ensuring get_password_reset_key() and register_new_user() do not fire profile_update in these flows (while preserving expected user_register behavior).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/wp-includes/user.php Bypasses wp_update_user() when saving user_activation_key to prevent unintended profile_update firing.
tests/phpunit/tests/user.php Adds regression tests to ensure the corrected action-firing behavior and key persistence.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/wp-includes/user.php
Comment on lines +3150 to 3154
$wpdb->update(
$wpdb->users,
array( 'user_activation_key' => $hashed ),
array( 'ID' => $user->ID )
);
Comment on lines +1592 to +1594
$updated_user = get_userdata( $user->ID );
$this->assertNotEmpty( $updated_user->user_activation_key, 'The user_activation_key should have been persisted.' );
}
@github-actions

Copy link
Copy Markdown

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

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.

2 participants