Make WordPress Core

Opened 6 weeks ago

Last modified 12 days ago

#65600 reviewing defect (bug)

XML-RPC: wp.getUsersBlogs, enforce arg string requirements

Reported by: josephscott Owned by: westonruter
Priority: normal Milestone: 7.2
Component: XML-RPC Version:
Severity: normal Keywords: has-patch has-unit-tests
Cc: Focuses:

Description

The current wp.getUsersBlogs XML-RPC method will generate a PHP fatal error when given something unexpected. The problem can be easily reproduced with:

curl -v -H 'Content-Type: text/xml' http://localhost:8889/xmlrpc.php --data '<?xml version="1.0"?><methodCall><methodName>wp.getUsersBlogs</methodName><params><param><value><string>testing</string></value></param><param><value><array><data></data></array></value></param></params></methodCall>'

That generates a fatal error condition, with a HTTP 500 response:

* Host localhost:8889 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:8889...
* Connected to localhost (::1) port 8889
> POST /xmlrpc.php HTTP/1.1
> Host: localhost:8889
> User-Agent: curl/8.7.1
> Accept: */*
> Content-Type: text/xml
> Content-Length: 216
> 
* upload completely sent off: 216 bytes
< HTTP/1.1 500 Internal Server Error
< Server: nginx/1.29.7
< Content-Type: text/xml; charset=UTF-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< X-Powered-By: PHP/8.3.30
< Expires: Wed, 11 Jan 1984 05:00:00 GMT
< Cache-Control: no-cache, must-revalidate, max-age=0, no-store, private
< Date: Wed, 08 Jul 2026 21:01:49 +0000
< 
<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
  <fault>
    <value>
      <struct>
        <member>
          <name>faultCode</name>
          <value><int>500</int></value>
        </member>
        <member>
          <name>faultString</name>
          <value><string>&lt;p&gt;There has been a critical error on this website.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://wordpress.org/documentation/article/faq-troubleshooting/&quot;&gt;Learn more about troubleshooting WordPress.&lt;/a&gt;&lt;/p&gt;</string></value>
        </member>
      </struct>
    </value>
  </fault>
</methodResponse>
* Connection #0 to host localhost left intact

In general WordPress shouldn't fall over with a fatal error when given something unexpected. I have a small patch to catch this condition, avoid the fatal error, and return something a bit more helpful ( with HTTP 200 ):

* Host localhost:8889 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:8889...
* Connected to localhost (::1) port 8889
> POST /xmlrpc.php HTTP/1.1
> Host: localhost:8889
> User-Agent: curl/8.7.1
> Accept: */*
> Content-Type: text/xml
> Content-Length: 216
> 
* upload completely sent off: 216 bytes
< HTTP/1.1 200 OK
< Server: nginx/1.29.7
< Content-Type: text/xml; charset=UTF-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< X-Powered-By: PHP/8.3.30
< Date: Wed, 08 Jul 2026 21:10:23 +0000
< 
<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
  <fault>
    <value>
      <struct>
        <member>
          <name>faultCode</name>
          <value><int>400</int></value>
        </member>
        <member>
          <name>faultString</name>
          <value><string>Invalid arguments passed to this XML-RPC method.  Requires two strings.</string></value>
        </member>
      </struct>
    </value>
  </fault>
</methodResponse>
* Connection #0 to host localhost left intact

Docs ( https://codex.wordpress.org/XML-RPC_wp#wp.getUsersBlogs ) and code comments ( https://github.com/WordPress/wordpress-develop/blob/585ec6c455c98bfbefe17499a28f1b58fbc2e497/src/wp-includes/class-wp-xmlrpc-server.php#L696 ) both indicate that the two args are expected to be a strings. That is what we should enforce.

Change History (8)

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


6 weeks ago
#1

  • Keywords has-patch has-unit-tests added

https://core.trac.wordpress.org/ticket/65600

AI assistance: Yes
Tool(s): Claude
Model(s): Opus 4.8
Used for: Writing the unit tests

This ticket was mentioned in Slack in #core by josephscott. View the logs.


5 weeks ago

#3 @westonruter
5 weeks ago

  • Milestone Awaiting Review7.1
  • Owner set to westonruter
  • Status newreviewing

#4 @josephscott
3 weeks ago

@westonruter are there any changes that you want to see on this?

This ticket was mentioned in Slack in #core by adrianduffell. View the logs.


2 weeks ago

#6 @westonruter
2 weeks ago

  • Milestone 7.17.2

@josephscott Sorry for the delay in reviewing. I left a review (via Claude Opus 5) which I think makes some key points to make this a more comprehensive fix.

In particular, the username/password checks can be moved a level lower as part of \wp_xmlrpc_server::login() so then all methods can take advantage of this. The method can be updated to take mixed for the $username and $password and then it can error out if either is not a string.

Given that this touches on a sensitive login area, and that we're very close to RC1, I'm punting to land early in 7.2 so this can have more time to soak.

#7 @westonruter
2 weeks ago

In 63006:

XML-RPC: Validate the attachment data in mw_newMediaObject().

Passing anything other than a struct as the fourth argument caused a fatal error, and because the struct was read before the login was attempted, an unauthenticated request was enough to trigger it.

Read and validate the struct only once the request is authenticated and the upload_files capability is confirmed, as every other method on the server does, and reject a call with too few arguments using minimum_args(). The name, type and bits members must all be strings: a struct sent for bits reached fwrite() by way of wp_upload_bits() and threw a TypeError, while one sent for type survived sanitize_mime_type() to reach the database as the attachment's post MIME type. A name left empty by sanitize_file_name() is now reported as a malformed request too, rather than as the server failure wp_upload_bits() produced for it.

The fourth argument is expanded into a nested hash in the documentation, covering the previously undocumented post_id member. Tests cover each rejected shape, the optional members that remain tolerated when absent, and the ordering of the login and capability checks ahead of the validation.

Developed in https://github.com/WordPress/wordpress-develop/pull/12482.
Follow-up to r32579, r53881.

Props josephscott, westonruter, mukesh27.
See #65600.
Fixes #65611.

#8 @josephscott
12 days ago

No problem. I've updated the PR to address the items that were brought up and to aim for WP 7.2.

Note: See TracTickets for help on using tickets.