PluginProbe
JetFormBuilder — Dynamic Blocks Form Builder / 3.6.6
JetFormBuilder — Dynamic Blocks Form Builder v3.6.6
3.6.6.1 3.6.6 3.6.5.4 3.6.5.3 3.6.5.2 3.6.5.1 3.6.5 3.6.4.2 3.6.4.1 3.6.4 3.6.3.1 3.6.3 3.6.2.2 3.6.2.1 3.6.2 3.6.1.1 3.6.1 3.6.0.1 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 All 134 releases
← All changes | includes/presets/sources/base-source.php +64 -12 3.6.1 → 3.6.6 View file →
@@ -147,28 +147,80 @@
147 147 return ( ! empty( $this->src() ) && ! is_wp_error( $this->src() ) );
148 148 }
149 149
150 150 /**
151 + * Whether this source allows the `restricted: false` opt-out (see
152 + * has_permission()) to skip can_get_preset() at all. A source can override
153 + * this to return false when its capability must never be made public by a
154 + * form's stored, trusted preset configuration.
155 + *
156 + * Preset_Source_Options_Page intentionally uses the default: a form author
157 + * can explicitly publish the selected Options Page field by switching
158 + * "Restrict access" off. Request-provided preset data cannot do so because
159 + * it never receives the trusted-origin marker. See issues-tracker #20359.
160 + *
151 161 * @return bool
162 + */
163 + protected function allows_restriction_bypass(): bool {
164 + return true;
165 + }
166 +
167 + /**
168 + * The `restricted: false` opt-out below only takes effect when both:
169 + * - `_trusts_restriction_flag` is true - a flag set programmatically by
170 + * Base_Preset::get_source() (never taken from preset_data itself, so
171 + * an attacker can't forge it) from whatever the CALL SITE declared via
172 + * Base_Preset::trust_restriction_flag(). Only origins that are
173 + * admin-authored declare trust: the form's own preset meta
174 + * (General_Preset), a field block's attributes
175 + * (Preset_Manager::get_field_value()) and the settings parsed via
176 + * jet_fb_parse_dynamic_trusted() (validation rules, date min/max,
177 + * conditional blocks, action conditions, dynamic value). Parsing a
178 + * submitted field value - jet_fb_parse_dynamic() via Rich_Content -
179 + * never does, so a `restricted` flag smuggled through a submitted
180 + * value is ignored there.
181 + * - allows_restriction_bypass() is true for this source (see above).
182 + *
183 + * This closes the access-control bypass reported in issues-tracker
184 + * #20359 while preserving the documented "Restrict access" editor
185 + * toggle for admin-configured presets.
186 + *
187 + * `jet-form-builder/preset-sanitize` runs on BOTH paths - the opt-out
188 + * result as well as can_get_preset() - so an integrator can always
189 + * further restrict access, including on presets whose author switched
190 + * the toggle off. Returning true from it does not grant access that
191 + * can_get_preset() denied on the checked path, because the filter only
192 + * ever sees an already-computed decision.
193 + *
194 + * @return bool
152 195 * @throws Preset_Exception
153 196 */
154 197 protected function has_permission(): bool {
155 - if (
156 - // not enabled programmatically
157 - empty( $this->preset_data['_check_restriction'] ) ||
158 - // disabled in preset-editor
159 - (
160 - array_key_exists( 'restricted', $this->preset_data ) &&
161 - ! $this->preset_data['restricted']
162 - )
163 - ) {
164 - return true;
165 - }
166 198 if ( is_null( $this->permission ) ) {
167 - $this->permission = apply_filters( 'jet-form-builder/preset-sanitize', $this->can_get_preset(), $this );
199 + $this->permission = apply_filters(
200 + 'jet-form-builder/preset-sanitize',
201 + $this->allows_restriction_bypass_for_data() ? true : $this->can_get_preset(),
202 + $this
203 + );
168 204 }
169 205
170 206 return $this->permission;
207 + }
208 +
209 + /**
210 + * Whether the `restricted: false` opt-out applies to this preset data.
211 + *
212 + * All four conditions must hold, see has_permission() above.
213 + *
214 + * @return bool
215 + */
216 + private function allows_restriction_bypass_for_data(): bool {
217 + return (
218 + ! empty( $this->preset_data['_trusts_restriction_flag'] ) &&
219 + $this->allows_restriction_bypass() &&
220 + array_key_exists( 'restricted', $this->preset_data ) &&
221 + ! $this->preset_data['restricted']
222 + );
171 223 }
172 224
173 225 /**
174 226 * @throws Preset_Exception