Commit 3938d15885 for wordpress.org
commit 3938d158859c4a9efe119b182e0a6e3843b76498
Author: ramonopoly <ramonopoly@git.wordpress.org>
Date: Sun Oct 18 22:53:49 2026 +0000
Editor: Remove theme.json preset items of unexpected types to prevent fatals in PHP
This commit prevents `WP_Theme_JSON` from throwing fatal TypeErrors when preset items in theme.json or global styles data contain values of the wrong type. Those values could be user- or AI-generated.
It does this by removing theme.json preset items that aren't objects, or whose `slug` isn't a scalar, in `WP_Theme_JSON::sanitize()`.
Previouly, for example, a preset list of strings, such as `"fontFamilies": [ "Inter" ]`, failed with `Cannot access offset of type string on string` when the stylesheet is generated.
Developed in: https://github.com/WordPress/wordpress-develop/pull/14262
Props ramonopoly, aaronrobertshaw, isabel_brison.
Fixes #66304.
Built from https://develop.svn.wordpress.org/trunk@64491
git-svn-id: http://core.svn.wordpress.org/trunk@63641 1a063a9b-81f0-0310-95a4-ce76da25c4cd
diff --git a/wp-includes/class-wp-theme-json.php b/wp-includes/class-wp-theme-json.php
index f5cdc1b43c..116a8ad951 100644
--- a/wp-includes/class-wp-theme-json.php
+++ b/wp-includes/class-wp-theme-json.php
@@ -1536,6 +1536,32 @@ class WP_Theme_JSON {
$result['viewport'] = self::sanitize_viewport_settings( $input[ $subtree ]['viewport'] );
}
+ if ( 'settings' === $subtree ) {
+ // Preset leaves are untyped in VALID_SETTINGS, but consumers read `$preset['slug']` as a string.
+ $is_valid_preset = static function ( $preset ) {
+ return is_array( $preset ) && ( ! isset( $preset['slug'] ) || is_scalar( $preset['slug'] ) );
+ };
+ foreach ( static::get_setting_nodes( array( 'settings' => $result ) ) as $node ) {
+ foreach ( static::PRESETS_METADATA as $preset_metadata ) {
+ $path = array_merge( array_slice( $node['path'], 1 ), $preset_metadata['path'] );
+ $presets = _wp_array_get( $result, $path, null );
+ if ( ! is_array( $presets ) ) {
+ continue;
+ }
+ if ( isset( $presets[0] ) ) {
+ $presets = array_values( array_filter( $presets, $is_valid_preset ) );
+ } else {
+ foreach ( static::VALID_ORIGINS as $origin ) {
+ if ( isset( $presets[ $origin ] ) && is_array( $presets[ $origin ] ) ) {
+ $presets[ $origin ] = array_values( array_filter( $presets[ $origin ], $is_valid_preset ) );
+ }
+ }
+ }
+ _wp_array_set( $result, $path, $presets );
+ }
+ }
+ }
+
if ( empty( $result ) ) {
unset( $output[ $subtree ] );
} else {
diff --git a/wp-includes/version.php b/wp-includes/version.php
index b9e895e42b..99c1adcdfb 100644
--- a/wp-includes/version.php
+++ b/wp-includes/version.php
@@ -16,7 +16,7 @@
*
* @global string $wp_version
*/
-$wp_version = '7.2-alpha-64490';
+$wp_version = '7.2-alpha-64491';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.