PluginProbe
Extendify / 3.2.1
Extendify v3.2.1
3.2.1 3.2.0 3.1.6 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.6 3.0.5 3.0.4 trunk 0.1.0 0.10.0 0.10.1 0.10.2 0.11.0 0.11.1 0.2.0 0.3.0 0.3.1 0.4.0 0.5.0 0.6.0 All 127 releases
← All changes | app/Shared/Services/BlockStyleVariations.php +44 -2 3.1.63.2.1 View file →
@@ -33,9 +33,15 @@
33 33 * @return void
34 34 */
35 35 public static function registerStored()
36 36 {
37 - self::registerNames(get_option(self::OPTION, []));
37 + $stored = get_option(self::OPTION, []);
38 + $valid = self::validBlockTypes($stored);
39 + if ($valid !== $stored) {
40 + update_option(self::OPTION, $valid);
41 + }
42 +
43 + self::registerNames($valid);
38 44 }
39 45
40 46 /**
41 47 * A design flow's write carries the names it needs, so nothing is fetched or
@@ -52,8 +58,13 @@
52 58 if (!$isWrite || strpos($request->get_route(), '/wp/v2/global-styles') !== 0) {
53 59 return $response;
54 60 }
55 61
62 + // This filter runs before the route's permission_callback, so auth is checked here.
63 + if (!current_user_can('edit_theme_options')) {
64 + return $response;
65 + }
66 +
56 67 $names = self::namesInWrite($request->get_param('styles'));
57 68 if (!$names) {
58 69 return $response;
59 70 }
@@ -72,8 +83,12 @@
72 83 {
73 84 $blocks = is_array($styles) ? ($styles['blocks'] ?? []) : [];
74 85 $names = [];
75 86 foreach ((array) $blocks as $blockType => $block) {
87 + if (!self::isValidBlockType($blockType)) {
88 + continue;
89 + }
90 +
76 91 $variations = is_array($block) ? ($block['variations'] ?? []) : [];
77 92 $ours = array_filter(array_keys((array) $variations), function ($name) {
78 93 return is_string($name) && strpos($name, 'ext-') === 0;
79 94 });
@@ -102,8 +117,31 @@
102 117 return $merged;
103 118 }
104 119
105 120 /**
121 + * A block-style key is interpolated unescaped into core's inline
122 + * registerBlockStyle() script, so only a real "namespace/block" name is
123 + * ever stored or registered — anything else is an injection attempt.
124 + *
125 + * @param mixed $blockType - The array key from a global-styles write.
126 + * @return bool
127 + */
128 + private static function isValidBlockType($blockType)
129 + {
130 + return is_string($blockType) && preg_match('~^[a-z0-9-]+/[a-z0-9-]+$~', $blockType) === 1;
131 + }
132 +
133 + /**
134 + * @param mixed $stored - The persisted names per block type.
135 + * @return array<string, array<string>>
136 + */
137 + private static function validBlockTypes($stored)
138 + {
139 + $names = is_array($stored) ? $stored : [];
140 + return array_filter($names, [self::class, 'isValidBlockType'], ARRAY_FILTER_USE_KEY);
141 + }
142 +
143 + /**
106 144 * @param mixed $names - Variation names per block type.
107 145 * @return void
108 146 */
109 147 private static function registerNames($names)
@@ -109,10 +147,14 @@
109 147 private static function registerNames($names)
110 148 {
111 149 $registry = \WP_Block_Styles_Registry::get_instance();
112 150 foreach ((array) $names as $blockType => $blockNames) {
151 + if (!self::isValidBlockType($blockType)) {
152 + continue;
153 + }
154 +
113 155 foreach ((array) $blockNames as $name) {
114 - if (!is_string($blockType) || !is_string($name) || $registry->is_registered($blockType, $name)) {
156 + if (!is_string($name) || $registry->is_registered($blockType, $name)) {
115 157 continue;
116 158 }
117 159
118 160 \register_block_style($blockType, ['name' => $name, 'label' => $name]);