[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
malformed.","data":{"status":400}}`.
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