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)
#2
@
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
@
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
@
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
@
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:
↓ 8
@
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
@
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.
This ticket was mentioned in Slack in #core-test by softglaze. View the logs.
3 weeks ago
#11
@
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
- From the Network dashboard, head over to Sites > Add Site
- Fill in all the input fields and notice the Site Title field is required.
- In the admin notice, click the Edit Site link.
- Click Settings, clear the blogname field and leave empty then Save Changes.
- Observe whether any error notice pops up and the state of the blogname field before and after applying the patch.
- ✅ 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
- Screencast before: https://files.catbox.moe/ujuci1.mp4
- Screencast after: https://files.catbox.moe/wunt80.mp4
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>
#12
@
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.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)
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,