diff --git a/includes/sanitizers/class-amp-form-sanitizer.php b/includes/sanitizers/class-amp-form-sanitizer.php index 5e2f48a2c90..c46cc9c08f9 100644 --- a/includes/sanitizers/class-amp-form-sanitizer.php +++ b/includes/sanitizers/class-amp-form-sanitizer.php @@ -67,9 +67,21 @@ public function sanitize() { $action_url = esc_url_raw( '//' . $_SERVER['HTTP_HOST'] . wp_unslash( $_SERVER['REQUEST_URI'] ) ); } else { $action_url = $node->getAttribute( 'action' ); - // Check if action_url is a relative path and add the host to it. + + // Handle relative URLs. if ( ! preg_match( '#^(https?:)?//#', $action_url ) ) { - $action_url = esc_url_raw( '//' . $_SERVER['HTTP_HOST'] . $action_url ); + $schemeless_host = '//' . $_SERVER['HTTP_HOST']; + if ( '?' === $action_url[0] || '#' === $action_url[0] ) { + // For actions consisting of only a query or URL fragment, include the schemeless-host and the REQUEST URI of the current page. + $action_url = $schemeless_host . wp_unslash( $_SERVER['REQUEST_URI'] ) . $action_url; + } elseif ( '.' === $action_url[0] ) { + // For actions consisting of relative paths (e.g. '../'), prepend the schemeless-host and a trailing-slashed REQUEST URI. + $action_url = $schemeless_host . trailingslashit( wp_unslash( $_SERVER['REQUEST_URI'] ) ) . $action_url; + } else { + // Otherwise, when the action URL includes an absolute path, just append it to the schemeless-host. + $action_url = $schemeless_host . $action_url; + } + $action_url = esc_url_raw( $action_url ); } } $xhr_action = $node->getAttribute( 'action-xhr' ); diff --git a/tests/php/test-amp-form-sanitizer.php b/tests/php/test-amp-form-sanitizer.php index 9966149078e..5d5a1debf35 100644 --- a/tests/php/test-amp-form-sanitizer.php +++ b/tests/php/test-amp-form-sanitizer.php @@ -93,7 +93,18 @@ public function get_data() { '
', '#' . preg_quote( '
', '#' ) . $form_template_pattern . '
#s', ], - + 'form_with_relative_path_action_url' => [ + '
', + '#' . preg_quote( '
', '#' ) . $form_template_pattern . '
#s', + ], + 'form_with_relative_query_action_url' => [ + '
', + '#' . preg_quote( '
', '#' ) . $form_template_pattern . '
#s', + ], + 'form_with_relative_fragment_action_url' => [ + '
', + '#' . preg_quote( '
', '#' ) . $form_template_pattern . '
#s', + ], 'test_with_dev_mode' => [ '
', null, // No change.