[wp-trac] [WordPress Trac] #53965: Legacy widgets used inside a normal block fail when salts are changed

WordPress Trac noreply at wordpress.org
Fri Aug 20 05:27:30 UTC 2021

#53965: Legacy widgets used inside a normal block fail when salts are changed
 Reporter:  Enchiridion               |      Owner:  (none)
     Type:  defect (bug)              |     Status:  new
 Priority:  normal                    |  Milestone:  Awaiting Review
Component:  Widgets                   |    Version:  5.8
 Severity:  normal                    |   Keywords:
  Focuses:  administration, rest-api  |
 When a legacy widget is added to the new block based widget area and it's
 a 1st level block, its data is stored the way widgets have always stored
 data.  However if a legacy widget block is used inside of a normal block
 its data is no longer stored separately in the options table, but is
 encoded and stored with its parent block.

 The legacy widget data is stored by base64 encoding its serialized data
 then generating a hash of it using `wp_hash()`.  Both pieces of data are
 stored in the parent block.  When viewing the widget block editor this
 data is hydrated.  The problem is the default scheme `AUTH` is used for
 `wp_hash()` when none is specified.  The value of AUTH is volatile.  Salt
 keys should be rotated occasionally and they can be changed via the `salt`
 filter, when that happens all the embedded legacy widgets will break.

 I can think of several ways to fix this:
 - Use a more stable salt.
 - Encode data using a method that doesn't rely on a hash for verification.
 - Remove the hash check.  I don't see anywhere in the codebase (but I'm
 far from an expert) where serialized data is compared against a hash
 before sending it to `unserialize()`, so I don't think it adds any more
 risk as it is supposed to be trusted data.  To me this is the cleanest
 solution, the first two methods would require a backwards compatibility
 fix: if the data failed to unserialize the new way, try the old method.

 The hash check to remove is in `\wp-includes\rest-api\endpoints\class-wp-
 rest-widget-types-controller.php` on lines 447 - 453. A couple other
 places in the method also need the hash references removed.  Luckily the
 `encode_form_data()` method is new and only used here so any changes won't
 be painful.

 I originally came across this issue because my new WP 5.8 site was having
 widget errors whenever it was migrated to the staging server.  My local
 server and staging server have different salt values, so it caused all the
 nested embedded widgets to fail. I was using some Navigation Menu widgets,
 which failed with the error `The "nav_menu" block was affected by errors
 and may not function properly. Check the developer tools for more
 details.` In dev tools this was the REST response
 `{"code":"rest_invalid_widget","message":"The provided instance is

 I verified the differing `AUTH_KEY`s were the issue by syncing them, which
 temporarily enabled the legacy widgets to work, however that isn't a
 realistic fix.

Ticket URL: <https://core.trac.wordpress.org/ticket/53965>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform

More information about the wp-trac mailing list