Make WordPress Core

Opened 6 weeks ago

Last modified 2 weeks ago

#65718 new defect (bug)

Multisite: the blogname is required during site creation but can be emptied later

Reported by: afercia Owned by:
Priority: normal Milestone: Future Release
Component: Networks and Sites Version:
Severity: normal Keywords: has-patch needs-testing
Cc: Focuses: multisite

Description

Discovered after Copilot review on an unrelated PR, see https://github.com/WordPress/wordpress-develop/pull/12683#discussion_r3653345968

When creating a new site, the 'Site Title' field is required. The value entered there is then used for the site blogname.

However, after the site is created, it is possible to edit the site, manually empty the blogname field and save.

At this point, the site will not have a blogname option, which is a problem because it is expected to be there and it is used in various parts of the admin including visually hidden text, aria-labels etc.

Change History (12)

#1 @hbhalodia
6 weeks ago

Hi @afercia, Thanks for the issue.

I have tested locally and found that it can be manually emptied from the general options. IMO, we should introduce a required field to blogname field which then validates server side, so that empty value cannot be entered. WDYT? is it the way to proceed?

Thanks,

Last edited 6 weeks ago by hbhalodia (previous) (diff)

#2 @abcd95
6 weeks ago

@hbhalodia I also confirmed the bug is real. Both the Network Admin → Sites → Edit → Settings tab and Settings → General accept an empty site title without any validation. No intentional design decision was found in Trac history, and it appears to me to be an oversight.

Simplest fixes I can think of is to make it required + server-side validation in the General Settings handler (following the timezone reset pattern in options.php), and skipping an empty blogname save in the network site-settings handler with a user-facing error notice.

References: site-new.php L86–88

#3 @hbhalodia
6 weeks ago

Thanks @abcd95,

Also to note, the Main network name is also being accepted as empty currently. The network name should also be required IMO.

So can we fix that within the scope of this issue?

Cc: @afercia

#4 @afercia
6 weeks ago

Personally, I would prefer server-side validation. However, maybe we're missing something and this may be intentional for some reason. I'd suggest to wait for feedback from someone more familiar with multisite Cc @realloc @johnjamesjacoby

This ticket was mentioned in PR #12706 on WordPress/wordpress-develop by @abcd95.


6 weeks ago
#5

  • Keywords has-patch added

#6 @realloc
6 weeks ago

Thanks all. I looked into this against trunk to check the scope of validating in sanitize_option().

On whether it is intentional: I found no clear evidence either way. The blogname branch in sanitize_option() was last touched in 2016 for emoji handling only. Core does already guard against an empty title on the read side, e.g. class-wp-automatic-updater.php, wp-admin/includes/misc.php and wp-admin/user-new.php all use '' !== get_option( 'blogname' ), so an empty title has at least been a tolerated state so far.

On PR #12706: validating in sanitize_option() is a single, consistent chokepoint. The caveat is how the failure is reported. When it sets $error, it resets the value to the stored one and only calls add_settings_error() if that function exists, which is effectively admin-only. On the admin screens the PR handles this well via a notice. Outside the admin the empty value is silently discarded with no feedback, which affects REST, the Customizer, XML-RPC wp.setOptions and WP-CLI.

The REST case is worth highlighting, because the block editor saves the site title through PUT /wp/v2/settings (title). Sending title: "" passes the REST schema (plain string, no minLength) and reaches update_option( 'blogname', '' ) in WP_REST_Settings_Controller::update_item(), where the return value is not checked. With the patch the value is rejected, the old title is kept, and the response is 200 OK with the previous title. So a user emptying the title in the editor gets no error, it just stays unchanged.

It may be worth deciding whether a silent reject is acceptable outside the admin, or whether the REST layer should return a real validation error instead. Happy to help test either way.

#7 follow-up: @realloc
6 weeks ago

One more note on the REST path: it can also empty the title in a way the patch would not catch.

In WP_REST_Settings_Controller::update_item(), title: null maps to delete_option( 'blogname' ), which bypasses sanitize_option(). The guard above only blocks this if the stored value fails schema validation, and a normal string title passes. So PUT /wp/v2/settings with title: null leaves get_option( 'blogname' ) empty, i.e. the same broken state.

Enforcing non-empty in sanitize_option() closes the update_option paths but not this delete_option one.

#8 in reply to: ↑ 7 @abcd95
6 weeks ago

  • Keywords needs-testing added

Replying to realloc:

Thanks @realloc, you're right.

I've reworked it: blogname now carries a minLength/pattern constraint on its REST schema, so PUT /wp/v2/settings with an empty or whitespace-only title gets a standard 400 validation error.

Tested all three admin surfaces plus the REST endpoint (empty, whitespace, null, and valid values). Left the Customizer/XML-RPC/WP-CLI question open as you suggested, since it's really a broader "should silent-reject be acceptable outside admin" decision rather than something specific to this ticket.

Also adding needs=testing so someone else could test all contexts, just to be absolutely sure.

#9 @realloc
5 weeks ago

  • Milestone Awaiting ReviewFuture Release

This ticket was mentioned in Slack in #core-test by softglaze. View the logs.


3 weeks ago

#11 @r1k0
2 weeks ago

Test Report

Patch tested: https://github.com/WordPress/wordpress-develop/pull/12706/

Environment

  • WordPress: 7.2-alpha-63166-src
  • Subdirectory: Yes
  • PHP: 8.3.33
  • Server: nginx/1.31.3
  • Database: mysqli (Server: 9.7.2 / Client: mysqlnd 8.3.33)
  • Browser: Chrome 151.0.0.0
  • OS: Windows 10/11
  • Theme: Twenty Twenty-Five 1.5
  • MU Plugins: None activated
  • Plugins:
    • Test Reports 1.3.1

Steps taken

  1. From the Network dashboard, head over to Sites > Add Site
  2. Fill in all the input fields and notice the Site Title field is required.
  3. In the admin notice, click the Edit Site link.
  4. Click Settings, clear the blogname field and leave empty then Save Changes.
  5. Observe whether any error notice pops up and the state of the blogname field before and after applying the patch.
  6. ✅ Patch is solving the problem.

Expected result

  • The blogname field should retain its initial value after clearing and saving.
  • An error notice pops up, stating that the field can't be empty.

Additional Notes

  • Other Test Cases

REST
With patch:

Code Message
Empty string("") 400 "Invalid parameter(s): title" & "title must be at least 1 character long."
Whitespace(" ") 400 "Invalid parameter(s): title" & "title does not match pattern \S."
null 400 "The site title cannot be empty. Please enter a title for your site."

WP-CLI
With patch:

Command Output
Empty string("") npm run env:cli -- option update blogname --url={url} Success: Value passed for 'blogname' option is unchanged.
Whitespace(" ") npm run env:cli -- option update blogname ' ' --url={url} Success: Value passed for 'blogname' option is unchanged.
Empty string("") npm run env:cli -- eval 'update_option( "blogname", "" );' --url={url} no output, blogname field in site setting remains unchanged
Whitespace(" ") npm run env:cli -- eval 'update_option( "blogname", " " );' --url={url} no output, blogname field in site setting remains unchanged
null npm run env:cli -- eval 'update_option( "blogname", null );' --url={url} no output, blogname field in site setting remains unchanged

While using wp option update the blogname remains unchanged; the output is misleading. I think it should read something like this

Error: 'blogname' option cannot be empty
Value for 'blogname' option is unchanged.

Customizer
Customize:

  • Empty Site Title field publishes successfully.
  • But the blogname field remains unchanged.

Site Editor:

  • An error message pops up "Invalid parameter(s): title"(from REST)
  • The message could be more useful to the user, possibly the message for a null title (The site title cannot be empty. Please enter a title for your site.)

XMLRPC

  • Silently rejects an empty string and whitespace, and the blogname field remains unchanged
  • Returns a response with the Site title unchanged.

Screenshots/Screencast with results

Support Content

XMLRPC code snippet

curl -L -X POST 'http://localhost:8890/thefirst/xmlrpc.php' \
-H 'Content-Type: application/xml' \
-u 'admin' \
-d '<?xml version="1.0"?>
<methodCall>
  <methodName>wp.setOptions</methodName>
  <params>
    <param>
      <value><int>3</int></value>
    </param>
    <param>
      <value><string>admin</string></value>
    </param>
    <param>
      <value><string>password</string></value>
    </param>
    <param>
      <value>
        <struct>
          <member>
            <name>blog_title</name>
            <value><string> </string></value>
          </member>
        </struct>
      </value>
    </param>
  </params>
</methodCall>'

XMLRPC response

<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
  <params>
    <param>
      <value>
      <struct>
  <member><name>blog_title</name><value><struct>
  <member><name>desc</name><value><string>Site Title</string></value></member>
  <member><name>readonly</name><value><boolean>0</boolean></value></member>
  <member><name>value</name><value><string>The First</string></value></member>
</struct></value></member>
</struct>
      </value>
    </param>
  </params>
</methodResponse>
Last edited 2 weeks ago by r1k0 (previous) (diff)

#12 @r1k0
2 weeks ago

To add to my report.

Yes, we should consider rejecting an empty site title with an error outside of the admin.

We can address this in a different ticket because the site title might be a required field throughout WordPress. An example would be the install.php page; currently, an empty site title is acceptable. This will likely apply to WP-CLI wp core install or wp core multisite-install,--title option as well.

Still on the install.php page with this PR, an empty site title doesn't trigger any error during submission. When you check the site title in options-general.php, it is pre-filled with My Site. Which I guess is coming from wp-admin/schema.php.

Last edited 2 weeks ago by r1k0 (previous) (diff)
Note: See TracTickets for help on using tickets.