From 8df2d6c91cac982b655acfe7db50a1491454be4d Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Fri, 12 Jun 2026 12:18:35 +0200 Subject: [PATCH 1/2] Guard URL field against non-scalar values validate_value() and format_value() in the URL field could receive a non-scalar value (e.g. an array) from a form submission and raised a TypeError from strpos()/esc_url(). Guard both so a non-string value is treated as invalid/empty rather than fatally erroring. Co-Authored-By: Claude Fable 5 --- includes/fields/class-acf-field-url.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/includes/fields/class-acf-field-url.php b/includes/fields/class-acf-field-url.php index 8333bda6..f54d7009 100644 --- a/includes/fields/class-acf-field-url.php +++ b/includes/fields/class-acf-field-url.php @@ -129,6 +129,11 @@ public function validate_value( $valid, $value, $field, $input ) { return $valid; } + // A non-string value (e.g. an array from a crafted submission) is never a valid URL. + if ( ! is_string( $value ) ) { + return __( 'Value must be a valid URL', 'secure-custom-fields' ); + } + if ( strpos( $value, '://' ) !== false ) { // url @@ -156,7 +161,8 @@ public function validate_value( $valid, $value, $field, $input ) { */ public function format_value( $value, $post_id, $field, $escape_html ) { if ( $escape_html ) { - return esc_url( $value ); + // esc_url() expects a string; treat a non-string value as empty. + return is_string( $value ) ? esc_url( $value ) : ''; } return $value; } From 3fdb3b38523316677d48730bfb0dea79ba41390e Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+cbravobernal@users.noreply.github.com> Date: Fri, 12 Jun 2026 12:18:43 +0200 Subject: [PATCH 2/2] Add regression tests for URL field non-scalar values Cover validate_value() and format_value() receiving an array value, ensuring they return an invalid/empty result instead of a TypeError. Co-Authored-By: Claude Fable 5 --- .../fields/test-class-acf-field-url.php | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/php/includes/fields/test-class-acf-field-url.php b/tests/php/includes/fields/test-class-acf-field-url.php index a3e3894d..73754fcb 100644 --- a/tests/php/includes/fields/test-class-acf-field-url.php +++ b/tests/php/includes/fields/test-class-acf-field-url.php @@ -137,6 +137,35 @@ public function test_validate_value_empty_required() { $this->assertTrue( $valid ); } + /** + * Test validate_value does not crash on a non-scalar value. + * + * A crafted form submission can deliver an array (e.g. acf[field_key][]) + * as the value. The field should treat it as invalid rather than raising + * a TypeError from strpos(). + */ + public function test_validate_value_non_scalar() { + $field = $this->get_field( array( 'required' => 1 ) ); + + $valid = $this->field_instance->validate_value( true, array( 'a' => 'b' ), $field, 'acf[field_url_test]' ); + + $this->assertEquals( __( 'Value must be a valid URL', 'secure-custom-fields' ), $valid ); + } + + /** + * Test format_value does not crash on a non-scalar value when escaping. + * + * Calling esc_url() on an array would raise a TypeError. The field should + * return an empty string, matching how it treats an empty value. + */ + public function test_format_value_non_scalar_escaped() { + $field = $this->get_field(); + + $result = $this->field_instance->format_value( array( 'a' => 'b' ), $this->post_id, $field, true ); + + $this->assertEquals( '', $result ); + } + /** * Test get_rest_schema returns valid schema. */