Skip to content

Conversation

@wil-gerken
Copy link
Contributor

All Submissions:

Changes proposed in this Pull Request:

This PR fixes a bug where special characters (accented letters, diacritics, punctuation, etc.) were being stripped from Guest Contributor display names during user creation. NPPM-2360

The root cause
When creating a Guest Contributor, the Display name value shares the username field. Because the username is passed through sanitize_user(), accented characters and other special characters are stripped from the Display name as well.

The proposed solution

  • Capture the original Display name value from $_POST['user_login'] before WordPress applies sanitize_user()
  • Sanitize the Display name using sanitize_text_field() with wp_unslash(), which preserves international characters while still preventing XSS/HTML injection
  • Continue using sanitize_user() for the generated username — no change here
  • Explicitly set the Display name to the accent-preserving, safely-sanitized value

How to test the changes in this Pull Request:

Before applying this PR (to reproduce the issue):

  1. In the admin dashboard, go to Users → Guest Authors → Create a new Guest Contributor
  2. Enter a Display name containing accented characters (e.g., Iñigo Montoya)
  3. Add the user
  4. Search for the user and click Edit
  5. Observe that the “Display name publicly as” field shows a name without accents
  6. Note that the username is URL-safe (e.g., inigo-montoya)

After applying this PR:

  1. In the admin dashboard, go to Users → Guest Authors → Create a new Guest Contributor
  2. Enter a Display name containing accented characters (e.g., Pepé Le Pew)
  3. Add the user
  4. Search for the user and click Edit
  5. Observe that the “Display name publicly as” field now preserves accents
  6. Confirm that the username remains URL-safe (e.g., pepe-le-pew)

Please also test with additional names and characters. For example: Sévêrüs Snāpê, Ph.D.

Security Considerations:
This fix uses wp_unslash() and sanitize_text_field() to safely process user input while preserving accented characters. This approach prevents XSS and HTML injection while allowing legitimate display names with accents, diacritics, and punctuation.

Note on phpcs:ignore
A phpcs:ignore WordPress.Security.NonceVerification.Missing comment was added for this change.

This logic runs on the user_profile_update_errors hook, which is triggered from wp-admin/user-new.php after WordPress has already verified the nonce. Since this hook does not have direct access to the earlier nonce verification, the ignore comment seems appropriate here, but I wanted to explicitly call it out for review.

Other information:

  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your changes, as applicable?
  • Have you successfully ran tests with your changes locally?

@wil-gerken wil-gerken requested a review from a team as a code owner January 21, 2026 00:47
Copy link
Contributor

@leogermani leogermani left a comment

Choose a reason for hiding this comment

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

Perfect!

Let me share what I did to check that this change was safe.

I looked at the hook that this function is tied to: https://developer.wordpress.org/reference/hooks/user_profile_update_errors/, and checked the source on WordPress to see where it was invoked.

It's invoked in https://developer.wordpress.org/reference/functions/edit_user/

My concern was that perhaps this hook could also be triggered in other contexts where there was nothing in the $_POST, like direct CLI commands or other cases. But looks like we're safe, edit_user() is precisely used to process form submissions and reads stuff from $_POST

(You might have gone the same route, just sharing my line of thought here as it might be helpful to see what I was looking for)

@github-actions github-actions bot added the [Status] Approved The pull request has been reviewed and is ready to merge label Jan 21, 2026
@wil-gerken
Copy link
Contributor Author

Excellent. Thank you @leogermani!

Let me share what I did to check that this change was safe.

Thank you for sharing all of the details on where to directly look! Very helpful to hear/read your process.

One thought does come to mind this morning... the code is currently this

// Get the original display name from POST data (before WordPress sanitizes it).
$original_display_name = isset( $_POST['user_login'] ) ? sanitize_text_field( wp_unslash( $_POST['user_login'] ) ) : '';

// Generate sanitized username from the original display name.
$user->user_login = self::generate_username( $original_display_name );

// Set display name to the sanitized value (preserves accents but removes HTML/scripts).
$user->display_name = $original_display_name;

Should we safeguard this and change that first line to the following, replacing '' with a better fallback of $user->user_login

// Get the original display name from POST data (before WordPress sanitizes it).
$original_display_name = isset( $_POST['user_login'] ) ? sanitize_text_field( wp_unslash( $_POST['user_login'] ) ) : $user->user_login;

This scenario shouldn't happen, but it feels safer to do it. The Display Name will lack accents, of course, but that's better than the potential of setting $user->user_login to ''.

Should I make this modification?

@leogermani
Copy link
Contributor

Mases sense @wil-gerken , I think it's a good change, yes.

@wil-gerken
Copy link
Contributor Author

Done. That's now in place.

@wil-gerken wil-gerken merged commit 20a612b into trunk Jan 21, 2026
8 checks passed
@wil-gerken wil-gerken deleted the fix/guest-contributor-display-name-special-chars branch January 21, 2026 20:20
@github-actions
Copy link

Hey @wil-gerken, good job getting this PR merged! 🎉

Now, the needs-changelog label has been added to it.

Please check if this PR needs to be included in the "Upcoming Changes" and "Release Notes" doc. If it doesn't, simply remove the label.

If it does, please add an entry to our shared document, with screenshots and testing instructions if applicable, then remove the label.

Thank you! ❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Status] Approved The pull request has been reviewed and is ready to merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants