www.holovaty.com Open in urlscan Pro
54.91.59.199  Public Scan

Submitted URL: http://go2.branch.io/MzE1LUZUVC0xMjEAAAGGgb_gFEJa1iYM1ZIUIL0vyRv7KpiUuqliAk2LJQYxCpSJPHSGJsd5TjniiSfenGRopk9rZtw=
Effective URL: https://www.holovaty.com/writing/framebust-native-apps/?utm_campaign=Mobile-Growth-News&utm_medium=email&utm_source=Mobil...
Submission: On August 29 via api from US — Scanned from DE

Form analysis 0 forms found in the DOM

Text Content

Adrian Holovaty > Writing


LET WEBSITES FRAMEBUST OUT OF NATIVE APPS

Written by Adrian Holovaty on August 10, 2022

Back in 1996, the website TotalNews.com had a brilliantly evil idea. Why not
make a single website that itself contained all the top American news websites,
directly embedded within?

After all, why should people go to the trouble of visiting the Washington Post
or New York Times websites directly? On TotalNews.com, the websites would be
available in one place, with easy navigation.

Using a new technology called the HTML <frame> element, TotalNews embedded the
top American news sites — content, design and everything! — in such a way that
the news was always fresh. (Because, well, it was literally those other
websites.)

Naturally, TotalNews added advertising around the news as well. It was only fair
for them to be compensated with ad revenue for providing this incredible
convenience.

--------------------------------------------------------------------------------

Yeah, it was the early, wild west days of the web — but you have to admire their
chutzpah. My own web browsing at the time was spent on Pearl Jam fan sites, so I
never saw TotalNews firsthand, but this Archive.org snapshot from December 1996
provides a vague picture.

Somehow news sites didn’t appreciate TotalNews misappropriating and profiting
from their content. So in February 1997, a group of them sued.

The case, The Washington Post, et als. v. TotalNews, Inc., et als., was settled
out of court, and TotalNews was prohibited from embedding the sites going
forward. This established a precedent, if not legally then at least culturally:
Framing without permission was not OK.

But the shady practice continued. So much, in fact, that “framebuster” scripts
became popular. This is the technique of putting some JavaScript in your site to
check whether it’s currently being framed — and “breaking out of” the frame as
needed. (See this excellent 2010 review of framebusting techniques and its
accompanying slide deck for a technical overview.) This is essentially website
self-defense.

Over time, web developers and security researchers realized there’s a more
serious reason a website would want to protect against framing: clickjacking.
That’s when, for example, a website frames your site, then hijacks user input
such that users are fooled into thinking they’re interacting with your site
while they’re actually providing data to the (evil) containing site. Imagine
typing your bank credentials into (what you think is) your bank website, whereas
it’s in fact an evil site logging everything you’ve typed.

These days, framebuster scripts are no longer necessary, because websites can
use a special HTTP header, X-Frame-Options, to block framing in an elegant and
effective way. And lovely web frameworks such as Django provide protection, via
that header, out of the box. Framebusting is more or less a solved problem.

Except in one major case.

--------------------------------------------------------------------------------

If you click a web link in the native Facebook, Instagram, Reddit or Twitter
apps on your smartphone, you won’t be taken to your phone’s web browser.
Instead, the app embeds the web page directly, so you don’t leave their
environment.

For example, here’s what I got in the Twitter iOS app when I clicked the link in
one of Simon Willison’s recent tweets:



To the untrained eye, this appears to be my phone’s web browser. It doesn’t
identify itself as Twitter anywhere, and it looks, well, pretty plain.

But in fact, this is something entirely different — a more ephemeral thing
called a “webview” or “in-app browser.” This is a way for a native app to embed
a mini web browser, while asserting control over the user experience and
attaching UI, functionality and other cruft. It looks like a separate browser,
but in fact it’s still the Twitter app in disguise.

Seem familiar? This is framing, merely in app form. But this time, the framed
website has no way to framebust.

It’s TotalNews — but for the 2020s, and much worse. These native apps aren’t
(for the most part) putting advertising around websites — but they’re
maintaining control over the user’s browsing experience, sometimes spying on
users, and providing various problems for the framed websites, with zero
recourse available for the users or website owners.

Somewhere along the way, despite a reasonably strong anti-framing culture,
framing moved from being a huge no-no to a huge shrug. In a web context, it’s
maligned; in a native app context, it’s totally ignored.

Why, precisely, is this bad? Here are four reasons. Each has a specific example,
and in almost each case I have direct experience in my work running Soundslice.


MISAPPROPRIATION

A native app can make misleading claims about the websites that it frames. And
due to the seamless way webviews are implemented, a nontechnical user would have
no way of knowing that they’re actually viewing a completely unaffiliated
website in context of the native app.

For example, a few years ago we got word that an Android app was embedding
Soundslice’s free MusicXML file viewer. The app was offering this as a “feature”
to their users.

We didn’t find out about it until they had the nerve to contact us to report a
bug regarding file upload within webviews.

We were doing everything right — our website already sends out the
X-Frame-Options: Deny header, meaning we don’t allow framing. Yet native apps
(and their mobile operating systems) ignore this header, which is a gaping
loophole.


POOR USER EXPERIENCE

If a native app opens a third-party website in a webview, that third-party site
will begin a new session, without existing cookies. It’s effectively like using
a web browser’s private (aka “incognito”) mode.

This means: If you’re logged into a website in your phone’s browser, but you
click a link to that site from a native app’s webview, your logged-in state will
not be honored. You’ll need to log in all over again.

At best, this is irritating. At worst, it gives people the false impression that
the website is broken or logged them out.

A specific example is Soundslice’s Instagram account, where we highlight stuff
people have created on our platform. If you see something on our Instagram and
want to add it to a practice list in your Soundslice account, you quickly run
into friction when opening the link within the Instagram app. Even if you’re
logged into Soundslice in your phone’s browser, the Instagram app doesn’t honor
your Soundslice login.

[Instagram is a particularly heinous example, because it doesn’t even let you
add a link to a post. If you enter a URL in an Instagram post, it will not turn
into a clickable link. Only one link, the one in your channel bio, is clickable.
An entire cottage industry has formed around this “link in bio” madness.]

Yes, you can copy-and-paste the URL (if the webview displays it), or you can
choose an “Open in web browser” option (if the webview provides it). But either
case requires nontrivial technical sophistication. Most users would just say
“Aw, man, I’ve somehow been logged out of Soundslice” and assign the blame to
us.

Proponents of native apps would likely argue “But it’s a better user experience
from the perspective of the native app! Because the user doesn’t have to
context-switch into a different environment, aka the web browser.” There was
indeed a time when this argument made sense: the years before 2015, which is
when iOS 9 introduced a global Back button conveniently solving the problem. And
of course Android has its global Back button. These days this argument holds no
water.

Proponents of native apps would also likely say: “If you had your own native
app, this problem would be solved, because you can register a link handler that
will automatically open all soundslice.com URLs in your native app.” iOS calls
this Universal Links; Android calls it App Links. This is true. It’s also an
unreasonable, disproportionate demand. I shouldn’t have to develop a native app
simply to wrangle control over how my website’s links are treated.


WEIRD, NON-STANDARD BROWSERS

Popular apps such as Instagram and Facebook don’t just use vanilla webviews.
They use customized ones, with their own quirks.

This means: If you click a link in the Facebook app and it opens in Facebook’s
webview, the website might be slightly broken. In my experience, page
dimensions/layout can be affected, and the website is provided incorrect
information about its environment.

I highly recommend reading Alex Russell’s piece Hobson’s Browser, full of
technical details on the deficiencies of in-app browsers.

A specific example is yet again Soundslice. Our main content type — the thing we
usually link to — is a piece of interactive sheet music, which is dynamically
sized to your screen. We’ve specifically had problems with the Instagram webview
not properly communicating its screen size — leading our site to apply incorrect
dimensions to the sheet music. Again, it’s a situation where we look bad due to
an obscure technical detail outside our control.

Hilariously, a few years ago a Facebook employee announced they added a way to
debug your website when it’s viewed in context of the Facebook in-app browser.
After I replied it’d be easier if Facebook just opened links in the default
browser in the first place, the employee rationalized the webview by saying it
helps protect people. Which brings us to:


SECURITY

This is the most important problem, though fortunately it’s the only one I
haven’t directly experienced in my own work.

When a native app embeds a website via a webview, the native app has control
over that page. Yes, even if it’s on a domain that the native app doesn’t
control (!). This means the native app can inject whatever JavaScript it likes
into any website that’s viewed in the webview.

Today I read an astounding exposé by Felix Krause, in which he discovered the
Facebook and Instagram iOS apps inject JavaScript into all web pages that are
viewed in their webviews. You should read and process this.

Facebook has a sterling reputation to uphold, so I’m sure they wouldn’t do
anything horrible here. But more nefarious apps could steal passwords or perform
other types of attacks.

The more I think about it, the more I cannot believe webviews with unfettered
JavaScript access to third-party websites ever became a legitimate, accepted
technology. It’s bad for users, and it’s bad for websites.

But fortunately, I think something can be done about all this.


A PROPOSED SOLUTION

Fundamentally this is about power. It’s a struggle between four participants:

 * The user wants to click a link to a website, retaining any useful state, with
   the ability to freely jump between apps/sites.
 * The website wants the user to have a smooth experience.
 * The native app wants to keep the user within its app (aka lock-in). In some
   cases, such as Facebook, the app wants to collect detailed information about
   the user’s browsing behavior.
 * The mobile operating system (iOS and Android) wants developers to build
   native apps on its platform. The web is a bit of an afterthought, a lower
   priority.
   
   

At the moment, the power is squarely in the hands of the last two. I believe it
should be more balanced, giving website owners a way to opt out of this behavior
— in old-school terms, a way to framebust.

So my proposal is this: Apple and Google should honor the existing
X-Frame-Options HTTP header in webviews. If a website is loaded into a webview,
and the website includes the appropriate X-Frame-Options header, the mobile OS
should immediately stop loading the webview and open the URL in the user’s
preferred web browser.

This elegantly uses an existing technology and gives websites a much-needed opt
out.

Unfortunately, the only way for this to happen would be to convince Apple and
Google to do it. I can’t imagine a general opt-out solution that doesn’t involve
iOS and Android providing hooks at the OS level. And, as Co-Monopolists Of The
World Of Native Phone Apps, Apple and Google have zero incentive to make such a
change.

It could in theory be implemented by individual apps, but I wouldn’t trust
Facebook to do this because of conflict of interest. And the sad precedent of
the Do Not Track header is instructive.

Our best bet is regulatory intervention, along the lines of what Open Web
Advocacy is doing. In collecting my thoughts here, I hope to start this
conversation. The modern version of TotalNews must be reined in.

Comments aren’t enabled for this page.