[wp-trac] [WordPress Trac] #39097: Links in embeds can't be opened in a new tab

WordPress Trac noreply at wordpress.org
Thu Apr 18 21:57:30 UTC 2019

#39097: Links in embeds can't be opened in a new tab
 Reporter:  smerriman                  |       Owner:  (none)
     Type:  defect (bug)               |      Status:  reopened
 Priority:  normal                     |   Milestone:  Awaiting Review
Component:  Embeds                     |     Version:  4.4
 Severity:  normal                     |  Resolution:
 Keywords:  needs-patch needs-testing  |     Focuses:

Comment (by iandunn):

 I encountered this bug today and I agree that it's a really bad UX, and an
 example of "[https://ponyfoo.com/articles/stop-breaking-the-web breaking
 the web]". Right-clicking, middle-clicking, and command-clicking are basic
 browser features that users expect to work, and I'm skeptical that there
 are ever any application features which justify breaking them.

 === Background

 I want to make sure I understand what's going on here correctly, though.
 This is what I've gathered:

 1. The raw HTML rendered by the host server just displays a standard link
 to the embed source
 1. To provide better UX, that link is then transformed into a rich preview
 via JavaScript
 1. The rich preview is rendered on the ''embed source's'' server, because
 that's the way the oEmbed protocol is designed
 1. Because the preview comes from a remote source, the host server can't
 trust it, and has to put it in a sandboxed `<iframe>`
 1. The `allow-top-navigation` value for the `sandbox` attribute was
 rejected because, when combined with `allow-scripts`,
 [https://github.com/swissspidy/oEmbed-API/issues/28#issue-100237451 it can
 be used to navigate away from the page programmatically], which would a
 vector for phishing attacks. Related discussions:
 [https://wordpress.slack.com/archives/C07LXSFV4/p1438584418000584 1],
 [https://wordpress.slack.com/archives/C07LXSFV4/p1437646363000360 2].
 1. Because the `<iframe>` is sandboxed, the browser will not normally open
 links inside it when they're clicked on.
 1. So, instead, the rich preview running on the ''embed source server''
 sends a `postMessage` via JavaScript to the  host server. The host server
 receives and authenticates that message, and then opens the link via the
 JavaScript running on the ''host'' server.
 1. The host server opens the link in the current window (via
 `window.top.location.href = data.value`), because opening in a new window
 would require `window.open`, which is blocked browsers unless it's the
 result of a direct user action.

 Is that all accurate?

 === Potential Solutions

 Here's some rough ideas, some/all of them may be unfeasible, but hopefully
 they'll spark something useful.

 * Could we remove the `postMessage` JS entirely, and instead use a value
 for the `sandbox` attribute which would allow links to work, without
 introducing security side-effects?  `allow-top-navigation`
 [https://github.com/swissspidy/oEmbed-API/issues/28 was rejected], but it
 doesn't seem like `allow-top-navigation-by-user-activation` was
 * Could we add `allow-top-navigation` but remove `allow-scripts` and the
 `postMessage` JS? It seems like the only remaining JS might be the sharing
 button, which could be redesigned to not require JS. Perhaps do something
 similar to the navigation menus that only use CSS.
 * Could we use `allow-popups` or `allow-popups-to-escape-sandbox` in some
 way? Maybe have `linkClickHandler` detect if it's a middle/command click,
 and do a `window.open()`. It seems like this would bypass popup blockers
 because it'd be triggered by a direct user action. We'd probably have to
 use the `escape-sandbox` variant, because the other would be blocked by `X
 -FRAME-OPTIONS` in many cases.
 * Maybe the WP oEmbed provider can supply the WP oEmbed consumer with the
 raw data via JSON, and the consumer can sanitize and then render the HTML?
 In that case we might not need the iframe at all, or could at least use
 looser permissions. It seems like the desire to allow JavaScript was so
 that 3rd-party embeds could embed "cool stuff", but I'm assuming we don't
 need that for a WP post. We could still allow that for 3rd-party embeds,
 and have this special solution for WP embeds. There may be back-compat
 concerns here, though.
 * Maybe the `postMessage` from the source server to the host server could
 tell the host server if it was a middle/cmd click. If it is, then the host
 could open it in a new tab. This probably wouldn't work since it wouldn't
 be interpreted by the browser as a user interaction, though.
 * Assuming that won't work, there may be some other approach where the
 source server can behave differently based on if the link was clicked on
 with a middle/cmd click.
 * Are there examples of other embeds solving this problem (inside or
 outside of WP)? It doesn't seem completely unique to us, so there may be
 other ideas we haven't thought of.

Ticket URL: <https://core.trac.wordpress.org/ticket/39097#comment:17>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform

More information about the wp-trac mailing list