From 3ce744a4a1a9ce3e997fe26eeaaccdbdcbca6a41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nauris=20P=C5=AB=C4=B7is?= Date: Wed, 10 Jul 2024 10:02:34 +0300 Subject: [PATCH] Jetpack Boost: Enhance Image and CSS Proxy with CDN and Caching (#38252) * Make sure CSS proxy only attempts to fetch CSS * Pass image guide requests through photon * esc_html the error message * Add plugins/boost changelog entry. * excess space * wp_parse_url * remove undefined variable * Make sure that $css is set * return void * Remove escess return * Use `wp_safe_remote_get` --- .../modules/image-guide/Image_Guide_Proxy.php | 12 +++++- .../optimizations/critical-css/CSS_Proxy.php | 41 +++++++++++++++---- .../plugins/boost/changelog/fix-boost-proxy | 4 ++ 3 files changed, 46 insertions(+), 11 deletions(-) create mode 100644 projects/plugins/boost/changelog/fix-boost-proxy diff --git a/projects/plugins/boost/app/modules/image-guide/Image_Guide_Proxy.php b/projects/plugins/boost/app/modules/image-guide/Image_Guide_Proxy.php index eb1d0e4954fcd..4d6ef31835cb7 100644 --- a/projects/plugins/boost/app/modules/image-guide/Image_Guide_Proxy.php +++ b/projects/plugins/boost/app/modules/image-guide/Image_Guide_Proxy.php @@ -2,6 +2,8 @@ namespace Automattic\Jetpack_Boost\Modules\Image_Guide; +use Automattic\Jetpack\Image_CDN\Image_CDN_Core; + /** * Add an ajax endpoint to proxy external CSS files. */ @@ -34,12 +36,18 @@ public static function handle_proxy() { wp_send_json_error( 'Invalid URL', 400 ); } - $response = wp_remote_get( $proxy_url ); + $photon_url = Image_CDN_Core::cdn_url( $proxy_url ); + $photon_url_domain = wp_parse_url( $photon_url, PHP_URL_HOST ); + $photon_domain = wp_parse_url( apply_filters( 'jetpack_photon_domain', 'https://i0.wp.com' ), PHP_URL_HOST ); + if ( $photon_url_domain !== $photon_domain ) { + wp_send_json_error( 'Failed to proxy the image.', 400 ); + } + + $response = wp_safe_remote_get( $photon_url ); if ( is_wp_error( $response ) ) { wp_send_json_error( 'error', 400 ); } wp_send_json_success( iterator_to_array( wp_remote_retrieve_headers( $response ) ) ); - die(); } } diff --git a/projects/plugins/boost/app/modules/optimizations/critical-css/CSS_Proxy.php b/projects/plugins/boost/app/modules/optimizations/critical-css/CSS_Proxy.php index ff9379278b9bb..0584aaf03627b 100644 --- a/projects/plugins/boost/app/modules/optimizations/critical-css/CSS_Proxy.php +++ b/projects/plugins/boost/app/modules/optimizations/critical-css/CSS_Proxy.php @@ -21,7 +21,7 @@ public static function init() { /** * AJAX handler to handle proxying of external CSS resources. * - * @return never + * @return void */ public function handle_css_proxy() { @@ -46,18 +46,41 @@ public function handle_css_proxy() { die( 'Invalid URL' ); } - $response = wp_remote_get( $proxy_url ); + $url_path = wp_parse_url( $proxy_url, PHP_URL_PATH ); + if ( ! $url_path || substr( strtolower( $url_path ), -4 ) !== '.css' ) { + wp_die( 'Invalid CSS file URL', 400 ); + } + + $cache_key = 'jb_css_proxy_' . md5( $proxy_url ); + $response = wp_cache_get( $cache_key ); + + if ( is_array( $response ) && isset( $response['error'] ) ) { + wp_die( esc_html( $response['error'] ), 400 ); + } + + $css = ''; + if ( false === $response ) { + $response = wp_safe_remote_get( $proxy_url ); + $content_type = wp_remote_retrieve_header( $response, 'content-type' ); + if ( strpos( $content_type, 'text/css' ) === false ) { + wp_cache_set( $cache_key, array( 'error' => 'Invalid content type. Expected CSS.' ), '', HOUR_IN_SECONDS ); + wp_die( 'Invalid content type. Expected CSS.', 400 ); + } + $css = wp_remote_retrieve_body( $response ); + wp_cache_set( $cache_key, $css, '', HOUR_IN_SECONDS ); + } + if ( is_wp_error( $response ) ) { // TODO: Nicer error handling. die( 'error' ); } - header( 'Content-type: text/css' ); - - // Outputting proxied CSS contents unescaped. - // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped - echo wp_strip_all_tags( $response['body'] ); - - die(); + if ( $css ) { + header( 'Content-type: text/css' ); + // Outputting proxied CSS contents unescaped. + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + echo wp_strip_all_tags( $css ); + die(); + } } } diff --git a/projects/plugins/boost/changelog/fix-boost-proxy b/projects/plugins/boost/changelog/fix-boost-proxy new file mode 100644 index 0000000000000..2b88d6792dd7a --- /dev/null +++ b/projects/plugins/boost/changelog/fix-boost-proxy @@ -0,0 +1,4 @@ +Significance: patch +Type: security + +Jetpack Boost: Improved image and CSS proxy functionalities with CDN support, caching, and other enhancements.