AI Search
Classic Search
 Search Phrase:
 Search Type:
Advanced search options
 Search in Forums:
 Search in date period:

 Sort Search Results by:

AI Assistant
Notifications
Clear all

first_name and last_name silently discarded on registration

4 Posts
2 Users
0 Reactions
1,189 Views
Posts: 2
 jboz
Topic starter
Translate
English
Spanish
French
German
Italian
Portuguese
Russian
Chinese
Japanese
Korean
Arabic
Hindi
Dutch
Polish
Turkish
Vietnamese
Thai
Swedish
Danish
Finnish
Norwegian
Czech
Hungarian
Romanian
Greek
Hebrew
Indonesian
Malay
Ukrainian
Bulgarian
Croatian
Slovak
Slovenian
Serbian
Lithuanian
Latvian
Estonian
(@jboz)
New Member
Joined: 2 months ago
[#73014]

wpForo 3.1.1 — first_name and last_name silently discarded on registration

Plugin: wpForo (Core)

Version: 3.1.1

File: wp-content/plugins/wpforo/includes/hooks.php

Function: wpforo_do_hook_user_register() (around line 2201)

Affects: any site whose registration form collects first_name / last_name via wpfreg[], e.g. when wpForo User Custom Fields adds them to the register form

Summary

In wpforo_do_hook_user_register(), the $wpfreg array is intersected with a four-key allowlist (user_login, user_email, user_pass1, user_pass2) before Members::update() is called. This silently strips any other fields posted via wpfreg[] — including first_name, last_name, and user_url, all of which are listed as save targets in Members::update_user_fields() at lines 948–957. The downstream save block then sees those keys as missing and skips the corresponding update_user_meta() calls. The registration completes successfully and the user is created, but with empty first_name and last_name in wp_usermeta.

This appears to be a security hardening (the inline comment mentions blocking attackers from pivoting userid via wpfreg[]) but the allowlist is overly restrictive — the userid is already forced on the next line, so widening the allowlist to include the standard WP user fields wpForo Core itself already saves doesn't reopen any attack surface.

Reproduction

  1. Install wpForo Core 3.1.1 + wpForo User Custom Fields (any recent version).
  2. Configure the registration form to include first_name and last_name (default UCF setup does this).
  3. Register a new user via the forum's /sign-up/ page, filling in First Name = FirstTest and Last Name = LastTest.
  4. Check the new user's meta: wp user meta list <id> | grep -E 'first_name|last_name'.

Expected: first_name = FirstTest, last_name = LastTest.
Actual: both empty.

Root cause

At includes/hooks.php ~line 2210:

$data['wpfreg'] = array_intersect_key( $wpfreg, array_flip( [
    'user_login',
    'user_email',
    'user_pass1',
    'user_pass2',
] ) );

The intersection drops first_name and last_name (and user_url) before WPF()->member->update() is called at line 2234, so Members::update_user_fields() never sees them.

Verified fix

Adding the three standard WP user fields back to the allowlist resolves the issue and re-saves them correctly via the existing update_user_meta() calls in update_user_fields():

$data['wpfreg'] = array_intersect_key( $wpfreg, array_flip( [
    'user_login',
    'user_email',
    'user_pass1',
    'user_pass2',
    'first_name',
    'last_name',
    'user_url',
] ) );

The $data['wpfreg']['userid'] = (int) $userid; line immediately below this still forces the trusted userid, so the security goal of the original change is preserved — the allowlist just needs to permit the additional standard WP user fields that Members::update_user_fields() already handles.

Logged evidence

Instrumented Members::create() and Members::update_user_fields() with error_log() calls, registered a user, then captured the $_POST, $data at entry to create(), $user_fields after the wpfreg split, and $data at the save gate. The trace shows first_name / last_name present in $_POST['wpfreg'] and in the post-split $user_fields, then absent from $data by the time it reaches the save block — confirming the allowlist intersection as the strip point. Re-running the same test after adding the three keys to the allowlist resulted in both fields landing in wp_usermeta as expected.

Notes

  • The strip is silent — no error, notice, or admin alert. The registration appears successful from every visible angle.
  • Sites using wpForo User Custom Fields to add other custom fields on the registration form aren't affected by those fields being lost, because UCF custom fields arrive under $_POST['data'] rather than $_POST['wpfreg'] and are handled separately. The strip only affects the standard WP user fields that arrive under wpfreg[].

3 Replies
Sofy
Posts: 5850
 Sofy
Admin
Translate
English
Spanish
French
German
Italian
Portuguese
Russian
Chinese
Japanese
Korean
Arabic
Hindi
Dutch
Polish
Turkish
Vietnamese
Thai
Swedish
Danish
Finnish
Norwegian
Czech
Hungarian
Romanian
Greek
Hebrew
Indonesian
Malay
Ukrainian
Bulgarian
Croatian
Slovak
Slovenian
Serbian
Lithuanian
Latvian
Estonian
(@sofy)
Support Team
Joined: 9 years ago

Sorry for the late response. 

This issue will be fixed in the next version of the wpForo plugin (no ETA yet).  


Reply
Posts: 2
 jboz
Topic starter
Translate
English
Spanish
French
German
Italian
Portuguese
Russian
Chinese
Japanese
Korean
Arabic
Hindi
Dutch
Polish
Turkish
Vietnamese
Thai
Swedish
Danish
Finnish
Norwegian
Czech
Hungarian
Romanian
Greek
Hebrew
Indonesian
Malay
Ukrainian
Bulgarian
Croatian
Slovak
Slovenian
Serbian
Lithuanian
Latvian
Estonian
(@jboz)
New Member
Joined: 2 months ago

Following up on this report - I'm afraid this is not fixed in 3.1.2, 3.1.3 or 3.1.4

I updated a production site to 3.1.4 on 24 July and the bug returned immediately. I've since compared the released packages from wordpress.org directly: includes/hooks.php is byte-identical across 3.1.1, 3.1.2, 3.1.3 and 3.1.4 - diff returns no output at all. wpforo_do_hook_user_register() still reads:

$data['wpfreg'] = array_intersect_key( $wpfreg, array_flip( [
    'user_login',
    'user_email',
    'user_pass1',
    'user_pass2',
] ) );

Searching the entire 3.1.1 -> 3.1.4 diff for first_name or last_name returns no matches anywhere in the plugin, so nothing in this code path has changed. I suspect the change simply didn't make it into the release.

To restate the mechanism: first_name, last_name and user_url are default profile fields with isDefault => 1, so Forms.php:1063 gives them varname 'wpfreg' and Forms.php:1121 renders them as name="wpfreg[first_name]". The allowlist above then strips them from $_POST['wpfreg'] before Members::update() runs, so Members::update_user_fields() (Members.php:952) never receives them and no update_user_meta() call happens. The saver is fine - the data is discarded upstream of it.

For completeness, in case this was closed against one of these: neither of the two changelog entries that look related actually touches this path.

  • 3.1.2 "Fixed: Issue with User Custom Fields addon, the missing fields data" - that's the $_POST['data'] branch. UCF-managed fields have isDefault falsy, so Forms.php:1063 gives them varname 'data' - a different branch of the same function. The UCF addon contains no reference to first_name or last_name at all.
  • 3.1.3/3.1.4 "Security: Fixed mass assignment bypass in profile and registration forms" - that's the custom_points / status / is_email_confirmed unsets added to Members.php. Also unrelated to the name fields.

On the fix itself: I understand why the allowlist was added and I'm not suggesting reverting it. But first_name, last_name and user_url are not privileged fields, and the userid pivot is already neutralised on the very next line by $data['wpfreg']['userid'] = (int) $userid;. Adding these three back restores the documented behaviour without weakening that hardening:

$data['wpfreg'] = array_intersect_key( $wpfreg, array_flip( [
    'user_login',
    'user_email',
    'user_pass1',
    'user_pass2',
    'first_name',
    'last_name',
    'user_url',
] ) );

Better still would be deriving the allowlist from the active registration form's field set rather than hardcoding it, so any enabled default field works and this can't regress again. Failing that, please consider adding a filter to the allowlist so site owners can work around it without editing plugin files - that's the part that has cost us most here.

Worth flagging the impact, because it is completely silent: registration succeeds, the names are lost with no error shown to anyone, and the values are unrecoverable afterwards. On our site 14 members registered in that state before it was spotted - and this is the second time, because the update reinstated the behaviour after we had patched it locally. We've now had to move our fix outside the plugin directory so your updates can't remove it again.

Happy to supply the diffs or any further detail if useful.

Thanks


Reply
1 Reply
Sofy
 Sofy
Admin
(@sofy)
Joined: 9 years ago

Support Team
Posts: 5850
Translate
English
Spanish
French
German
Italian
Portuguese
Russian
Chinese
Japanese
Korean
Arabic
Hindi
Dutch
Polish
Turkish
Vietnamese
Thai
Swedish
Danish
Finnish
Norwegian
Czech
Hungarian
Romanian
Greek
Hebrew
Indonesian
Malay
Ukrainian
Bulgarian
Croatian
Slovak
Slovenian
Serbian
Lithuanian
Latvian
Estonian

@jboz

Thank you for letting us know. This topic has already been forwarded to our development team, and they will definitely take this into consideration.


Reply
Share: