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

Make sure the WP embeds security process is applied #4226

Merged
merged 1 commit into from
Feb 21, 2018
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
30 changes: 20 additions & 10 deletions blocks/library/embed/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,13 @@ function getEmbedBlockSettings( { title, icon, category = 'embed', transforms, k
return;
}
response.json().then( ( obj ) => {
const { html, type, provider_name: providerName } = obj;
const { html, provider_name: providerName } = obj;
const providerNameSlug = kebabCase( toLower( providerName ) );
let { type } = obj;

if ( includes( html, 'class="wp-embedded-content" data-secret' ) ) {
type = 'wp-embed';
}
if ( html ) {
this.setState( { html, type, providerNameSlug } );
setAttributes( { type, providerNameSlug } );
Expand Down Expand Up @@ -194,6 +198,20 @@ function getEmbedBlockSettings( { title, icon, category = 'embed', transforms, k
const parsedUrl = parse( url );
const cannotPreview = includes( HOSTS_NO_PREVIEWS, parsedUrl.host.replace( /^www\./, '' ) );
const iframeTitle = sprintf( __( 'Embedded content from %s' ), parsedUrl.host );
const embedWrapper = 'wp-embed' === type ? (
<div
className="wp-block-embed__wrapper"
dangerouslySetInnerHTML={ { __html: html } }
/>
) : (
<div className="wp-block-embed__wrapper">
<SandBox
html={ html }
title={ iframeTitle }
type={ type }
/>
</div>
);
let typeClassName = 'wp-block-embed';
if ( 'video' === type ) {
typeClassName += ' is-video';
Expand All @@ -207,15 +225,7 @@ function getEmbedBlockSettings( { title, icon, category = 'embed', transforms, k
<p className="components-placeholder__error"><a href={ url }>{ url }</a></p>
<p className="components-placeholder__error">{ __( 'Previews for this are unavailable in the editor, sorry!' ) }</p>
</Placeholder>
) : (
<div className="wp-block-embed__wrapper">
<SandBox
html={ html }
title={ iframeTitle }
type={ type }
/>
</div>
) }
) : embedWrapper }
{ ( caption && caption.length > 0 ) || isSelected ? (
<RichText
tagName="figcaption"
Expand Down
2 changes: 1 addition & 1 deletion lib/client-assets.php
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ function gutenberg_register_scripts_and_styles() {
wp_register_script(
'wp-edit-post',
gutenberg_url( 'edit-post/build/index.js' ),
array( 'jquery', 'heartbeat', 'wp-element', 'wp-components', 'wp-editor', 'wp-i18n', 'wp-date', 'wp-utils', 'wp-data' ),
array( 'jquery', 'heartbeat', 'wp-element', 'wp-components', 'wp-editor', 'wp-i18n', 'wp-date', 'wp-utils', 'wp-data', 'wp-embed' ),
filemtime( gutenberg_dir_path() . 'edit-post/build/index.js' ),
true
);
Expand Down
46 changes: 46 additions & 0 deletions lib/compat.php
Original file line number Diff line number Diff line change
Expand Up @@ -197,3 +197,49 @@ function gutenberg_register_rest_api_post_type_capabilities() {
);
}
add_action( 'rest_api_init', 'gutenberg_register_rest_api_post_type_capabilities' );

/**
* Make sure oEmbed REST Requests apply the WP Embed security mechanism for WordPress embeds.
*
* @see https://core.trac.wordpress.org/ticket/32522
*
* TODO: This is a temporary solution. Next step would be to edit the WP_oEmbed_Controller,
* once merged into Core.
*
* @since 2.3.0
*
* @param WP_HTTP_Response|WP_Error $response The REST Request response.
* @param WP_REST_Server $handler ResponseHandler instance (usually WP_REST_Server).
* @param WP_REST_Request $request Request used to generate the response.
* @return WP_HTTP_Response|object|WP_Error The REST Request response.
*/
function gutenberg_filter_oembed_result( $response, $handler, $request ) {
if ( 'GET' !== $request->get_method() ) {
return $response;
}

if ( is_wp_error( $response ) && 'oembed_invalid_url' !== $response->get_error_code() ) {
return $response;
}

// External embeds.
if ( '/oembed/1.0/proxy' === $request->get_route() ) {
if ( is_wp_error( $response ) ) {
// It's possibly a local post, so lets try and retrieve it that way.
$post_id = url_to_postid( $_GET['url'] );
$data = get_oembed_response_data( $post_id, apply_filters( 'oembed_default_width', 600 ) );

if ( ! $data ) {
// Not a local post, return the original error.
return $response;
}
$response = (object) $data;
}

// Make sure the HTML is run through the oembed sanitisation routines.
$response->html = wp_oembed_get( $_GET['url'], $_GET );
}

return $response;
}
add_filter( 'rest_request_after_callbacks', 'gutenberg_filter_oembed_result', 10, 3 );