Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: harden usage and output of attribute values #1530

Merged
merged 5 commits into from
Sep 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 36 additions & 7 deletions includes/class-newspack-blocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -543,13 +543,15 @@ public static function image_size_for_orientation( $orientation = 'landscape' )
),
);

foreach ( $sizes[ $orientation ] as $key => $dimensions ) {
$attachment = wp_get_attachment_image_src(
get_post_thumbnail_id( get_the_ID() ),
'newspack-article-block-' . $orientation . '-' . $key
);
if ( ! empty( $attachment ) && $dimensions[0] === $attachment[1] && $dimensions[1] === $attachment[2] ) {
return 'newspack-article-block-' . $orientation . '-' . $key;
if ( isset( $sizes[ $orientation ] ) ) {
foreach ( $sizes[ $orientation ] as $key => $dimensions ) {
$attachment = wp_get_attachment_image_src(
get_post_thumbnail_id( get_the_ID() ),
'newspack-article-block-' . $orientation . '-' . $key
);
if ( ! empty( $attachment ) && $dimensions[0] === $attachment[1] && $dimensions[1] === $attachment[2] ) {
return 'newspack-article-block-' . $orientation . '-' . $key;
}
}
}

Expand Down Expand Up @@ -1494,5 +1496,32 @@ public static function get_color_for_contrast( $hex ) {
return 'white';
}
}

/**
* Get an array of allowed HTML attributes for sanitizing image markup.
* For use with wp_kses: https://developer.wordpress.org/reference/functions/wp_kses/
*
* @return array
*/
public static function get_sanitized_image_attributes() {
return [
'img' => [
'alt' => true,
'class' => true,
'data-*' => true,
'decoding' => true,
'height' => true,
'loading' => true,
'sizes' => true,
'src' => true,
'srcset' => true,
'width' => true,
],
'noscript' => [],
'a' => [
'href' => true,
],
];
}
}
Newspack_Blocks::init();
39 changes: 15 additions & 24 deletions src/blocks/carousel/view.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ function newspack_blocks_render_block_carousel( $attributes ) {
$hide_publish_date = apply_filters( 'newspack_listings_hide_publish_date', false ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
$show_author = $attributes['showAuthor'] && ! $hide_author;
$show_date = $attributes['showDate'] && ! $hide_publish_date;

// Validate the value of the "image fit" attribute.
$image_fits = [ 'cover', 'contain' ];
$image_fit = in_array( $attributes['imageFit'], $image_fits, true ) ? $attributes['imageFit'] : $image_fits[0];
?>

<article data-post-id="<?php echo esc_attr( $post_id ); ?>" class="<?php echo esc_attr( implode( ' ', $article_classes ) . ' ' . $post_type ); ?>">
Expand All @@ -86,9 +90,9 @@ function newspack_blocks_render_block_carousel( $attributes ) {
the_post_thumbnail(
'large',
array(
'object-fit' => $attributes['imageFit'],
'object-fit' => $image_fit,
'layout' => 'fill',
'class' => 'contain' === $attributes['imageFit'] ? 'image-fit-contain' : 'image-fit-cover',
'class' => 'contain' === $image_fit ? 'image-fit-contain' : 'image-fit-cover',
'alt' => trim( wp_strip_all_tags( get_the_title( $post_id ) ) ),
)
);
Expand Down Expand Up @@ -204,21 +208,7 @@ function newspack_blocks_render_block_carousel( $attributes ) {
if ( $attributes['showAvatar'] ) :
echo wp_kses(
newspack_blocks_format_avatars( $authors ),
array(
'img' => array(
'class' => true,
'src' => true,
'alt' => true,
'width' => true,
'height' => true,
'data-*' => true,
'srcset' => true,
),
'noscript' => array(),
'a' => array(
'href' => true,
),
)
Newspack_Blocks::get_sanitized_image_attributes()
);
endif;
?>
Expand Down Expand Up @@ -259,8 +249,9 @@ function newspack_blocks_render_block_carousel( $attributes ) {
);
}

$slides_per_view = absint( ! empty( $attributes['slidesPerView'] ) ? $attributes['slidesPerView'] : 1 );
$slides_per_view = absint( $attributes['slidesPerView'] ?? 1 );
$slides_to_show = $slides_per_view <= $counter ? $slides_per_view : $counter;
$aspect_ratio = floatval( $attributes['aspectRatio'] ?? 0.75 );

if ( $is_amp ) {
$selector = sprintf(
Expand All @@ -272,14 +263,14 @@ function newspack_blocks_render_block_carousel( $attributes ) {

$carousel = sprintf(
'<amp-base-carousel class="wp-block-newspack-carousel__amp-carousel" width="%1$s" height="%2$s" heights="%3$s" layout="responsive" snap="true" data-next-button-aria-label="%4$s" data-prev-button-aria-label="%5$s" controls="auto" loop="true" %6$s id="wp-block-newspack-carousel__amp-carousel__%7$s" on="slideChange:wp-block-newspack-carousel__amp-pagination__%7$s.toggle(index=event.index, value=true)" advance-count="1" visible-count="%8$s">%9$s</amp-base-carousel>',
$attributes['slidesPerView'] * 1,
$attributes['aspectRatio'],
'(min-width: 1168px) ' . ( $attributes['aspectRatio'] / $slides_to_show * 100 ) . '% !important, (min-width: 782px) ' . ( $slides_to_show > 1 ? ( $attributes['aspectRatio'] / 2 * 100 ) . '% !important' : ( $attributes['aspectRatio'] * 100 ) . '% !important' ) . ', ' . ( $attributes['aspectRatio'] * 100 ) . '% !important',
esc_attr( $slides_per_view * 1 ),
esc_attr( $aspect_ratio ),
esc_attr( '(min-width: 1168px) ' . ( $aspect_ratio / $slides_to_show * 100 ) . '% !important, (min-width: 782px) ' . ( $slides_to_show > 1 ? ( $aspect_ratio / 2 * 100 ) . '% !important' : ( $aspect_ratio * 100 ) . '% !important' ) . ', ' . ( $aspect_ratio * 100 ) . '% !important' ),
esc_attr__( 'Next Slide', 'newspack-blocks' ),
esc_attr__( 'Previous Slide', 'newspack-blocks' ),
$autoplay ? 'auto-advance="true" auto-advance-interval=' . esc_attr( $delay * 1000 ) : '',
absint( $newspack_blocks_carousel_id ),
'(min-width: 1168px) ' . $slides_to_show . ', (min-width: 782px) ' . ( $slides_to_show > 1 ? 2 : 1 ) . ', ' . 1,
esc_attr( '(min-width: 1168px) ' . $slides_to_show . ', (min-width: 782px) ' . ( $slides_to_show > 1 ? 2 : 1 ) . ', ' . 1 ),
$slides
);
$autoplay_ui = $autoplay ? newspack_blocks_carousel_block_autoplay_ui_amp( $newspack_blocks_carousel_id ) : '';
Expand All @@ -304,9 +295,9 @@ function newspack_blocks_render_block_carousel( $attributes ) {
}
$data_attributes = [
'data-current-post-id=' . $post_id,
'data-slides-per-view=' . $attributes['slidesPerView'],
'data-slides-per-view=' . esc_attr( $slides_per_view ),
'data-slide-count=' . $counter,
'data-aspect-ratio=' . $attributes['aspectRatio'],
'data-aspect-ratio=' . esc_attr( $aspect_ratio ),
];

if ( $autoplay && ! $is_amp ) {
Expand Down
18 changes: 2 additions & 16 deletions src/blocks/homepage-articles/templates/article.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ function( $data ) {
$post_link = Newspack_Blocks::get_post_link( $post_id );

if ( 'behind' === $attributes['mediaPosition'] && $attributes['showImage'] && has_post_thumbnail() ) {
$styles = 'min-height: ' . $attributes['minHeight'] . 'vh; padding-top: ' . ( $attributes['minHeight'] / 5 ) . 'vh;';
$styles = 'min-height: ' . absint( $attributes['minHeight'] ) . 'vh; padding-top: ' . ( absint( $attributes['minHeight'] ) / 5 ) . 'vh;';
}
$image_size = 'newspack-article-block-uncropped';
if ( has_post_thumbnail() && 'uncropped' !== $attributes['imageShape'] ) {
Expand Down Expand Up @@ -231,21 +231,7 @@ class="<?php echo esc_attr( implode( ' ', $classes ) ); ?>"
if ( $attributes['showAvatar'] ) :
echo wp_kses(
newspack_blocks_format_avatars( $authors ),
array(
'img' => array(
'class' => true,
'src' => true,
'alt' => true,
'width' => true,
'height' => true,
'data-*' => true,
'srcset' => true,
),
'noscript' => array(),
'a' => array(
'href' => true,
),
)
Newspack_Blocks::get_sanitized_image_attributes()
);
endif;
?>
Expand Down
11 changes: 9 additions & 2 deletions src/blocks/homepage-articles/view.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ function newspack_blocks_hpb_maximum_image_width() {
$site_content_width = 1200;
$is_image_half_width = in_array( $attributes['mediaPosition'], [ 'left', 'right' ], true );
if ( 'grid' === $attributes['postLayout'] ) {
$columns = $attributes['columns'];
$columns = absint( $attributes['columns'] );
if ( $is_image_half_width ) {
// If the media position is on left or right, the image is 50% of the column width.
$columns = $columns * 2;
Expand Down Expand Up @@ -284,7 +284,14 @@ function newspack_blocks_register_homepage_articles() {
function newspack_blocks_format_avatars( $author_info ) {
$elements = array_map(
function ( $author ) {
return sprintf( '<a href="%s">%s</a>', $author->url, $author->avatar );
return sprintf(
'<a href="%s">%s</a>',
esc_url( $author->url ),
wp_kses(
$author->avatar,
Newspack_Blocks::get_sanitized_image_attributes()
)
);
},
$author_info
);
Expand Down
4 changes: 3 additions & 1 deletion src/blocks/video-playlist/view.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,9 @@ function( $block ) {
}
);
foreach ( $youtube_blocks as $youtube_block ) {
$videos[] = $youtube_block['attrs']['url'];
if ( isset( $youtube_block['attrs']['url'] ) ) {
$videos[] = esc_url( $youtube_block['attrs']['url'] );
}
}
}

Expand Down
15 changes: 1 addition & 14 deletions src/templates/author-profile-card.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,20 +60,7 @@ function( $data ) {

echo wp_kses(
$author['avatar'],
[
'img' => [
'alt' => true,
'class' => true,
'data-*' => true,
'decoding' => true,
'height' => true,
'loading' => true,
'sizes' => true,
'src' => true,
'srcset' => true,
'width' => true,
],
]
Newspack_Blocks::get_sanitized_image_attributes()
);

if ( $show_archive_link ) :
Expand Down