[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
considered.
* 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