Hi All,

This email has unfortunately taken longer to send then I wish, mostly
because I've been on vacation and travelling for the past three weeks,
hence feedback on this is more urgent than usual.

We've had numerous threads on this list about trusted apps being different
from "plain" apps in a few ways. As we've been diving into the details
about how to implement trusted apps, we have realized some big problems
with the design we had in mind. Hence I'm proposing a new solution for how
trusted apps will work.

Please note that the various requirements and solutions in this email
*only* applies to trusted and certified apps. It does *not* apply to
"normal" apps, i.e. apps which don't use of any of the APIs which are only
available higher privilege apps. You will be able to do anything that you
can do in a web page today, and more, without worrying about any of the
restrictions in this email.

With that, let me start by enumerating the requirements that we have had in
mind for trusted apps:

* They are reviewed in some form. I.e. a trusted party has indicated some
level of trust in the application. In the initial version of B2G we've had
as a requirement that the store should review the actual app contents. In
future releases I'd also like to support stores indicating trust in the app
developer rather than the app itself, but this isn't slated for the initial
B2G release.
* They are signed. This is needed in order to verify that the app actually
contains the reviewed content. It also protects against someone hacking the
webserver which the app is served from.
* They use a minimum CSP policy in all pages in the app. This to ensure
that the app doesn't get hacked using XSS attacks. I.e. we want to ensure
that only the app developer's code runs, and not an attacker's code.
Obviously this will never be perfect, but it will hopefully help a lot.
* The resources in a trusted app should use a different "cookie jar" than
resources from the developer's website. This so that the trusted app can
rely that the data it stores in cookies, indexedDB, etc isn't compromised.
I.e. this is to further make it possible to hack a trusted app by hacking
the developer's website and overwriting data which the trusted app relies
on to make it behave in ways it otherwise wouldn't.
* The resources in a trusted app should not be "same origin" with any
resources other than ones from the same trusted app. I.e. if a trusted app
creates an <iframe> pointing to the developer's website, javascript running
inside the iframe shouldn't be able to reach out and touch the objects in
the trusted app. This is since otherwise it would obviously be
significantly easier to hack a trusted app by hacking any websites that it
opens in <iframe>s.

Our initial thoughts for how to implement these requirements were that
trusted apps should use largely the same delivery mechanism as normal apps.
I.e. they should live as normal files on the developer's web server. The
resources would then be cached using the normal app cache. The signatures
for the reviewed files would be gotten from the store at the time of
installation as well as any time the app is updated.

We came up with this solution since we wanted to avoid "packaging" apps
into some sort of archive (like zip) and delivering it through the store.
W3C widget specs and Chrome apps use this solution.

However, there are a couple of problems with this solution.

As Brian Smith has pointed out, signing HTTP responses isn't trivial.
There's a significant risk that proxies will change headers on the way
between the server and the user's browser. There even some risk that
proxies will change the contents of the response bodies themselves. During
normal browsing this isn't a big deal. But when the responses are signed it
means that the response is completely rejected, leading to a very bad user
experience. The only way to really prevent this is to always use https to
serve the resources. However, this can be a non-trivial cost for the app
developer.

Once we have several stores, stores will inevitably take a differently long
time to review an update of an app. This will cause confusion since the
different stores will be serving different signatures for the resources of
the app. One solution would be for the app developer to always use new URLs
for every version of the app. However, this is problematic if you are
developing a twitter app and want to enable sending emails containing links
to individual tweets since those links would then point to a specific
version of the app. Another solution would be for stores to not serve the
new signatures until the developer says that the new version is published,
and then for the developer to publish the new version only once all stores
have reviewed the new version. But this limits publishing speed to the
slowest store, which is likely not acceptable, and also means that no store
has an incentive to review quickly.

Additionally, there are some things that are very non-webby with this
solution.

Signing the resources means that you can no longer generate your HTML or
image files on the fly using php, perl, ruby, etc. This is because you
would have to generate a new signature at the same time as you generate the
file contents. However generating a new signature would require having the
private key on your web server, which largely defeats the purpose of
signing since if someone hacks the web server, they can create their own
signed resources. Hence signing effectively requires that the resources are
static files located on the server.

Also, since it's the store that has to review the app and send new
signatures for any updated version, it means that publishing a new version
of your app no longer means simply updating the contents of your web
server. You also have to contact the stores which you are selling your apps
through and ask them to re-review your app and create new signatures for
the app's resources.


When looking at the proposed solution this way it seems like we have come
up with something that is the worst of both worlds. App developers are
forced to create apps which consist of static resources and every time they
want to publish a new version they have to contact all stores that they
want to sell their app through. This feels a lot like a packaged app, the
only difference is that the resources live as separate files on the
developers server rather than as a zip file in the store. Yet app
developers have to serve their apps through SSL and deal with coordinating
publishing through multiple stores. This is non-webby, a pain to publish
through and potentially expensive.

Hence we have changed the plan to instead base trusted apps on a "packaged"
solution. The idea will be that to publish a trusted app the developer will
create a zip archive which contains the app manifest as well as all
resources needed for the app. The app can then be sent to all stores which
the developer wants to publish the app trough. These stores can then review
the app and sign the package. At installation time the signed package is
downloaded by the B2G from the store and the package is verified against
the signature.


One obvious question once you go with a packaged solution is what URLs the
packaged resources will be available through. My initial thought was to
keep things as webby as possible and to make the resources in the package
available as normal http or https URLs. The goal was that packaged apps
would behave as much as possible as non-packaged apps. This would mean that
in a trusted app a page that was part of the app would have URL
https://developer.com/myapp.html, and a page which was part of the
developer's website would have the URL https://developer.com/index.html.
Yet the two pages would use different cookies, and any same-origin checks
would have to say that the two pages are different. This is to satisfy the
last two requirements in the bullet list at the beginning of this email.
This is certainly implementable, however it seems very confusing for
developers.

Instead I think that we introduce a new protocol, app://, which is used to
load all resources in trusted apps. This is an idea that Jim Straus came up
with over in bug 707625. Introducing this new protocol certainly has the
disadvantage that it feels less webby, however I think the benefit in
clearing up the confusion above outweighs it. It makes it very clear which
pages will receive which cookies, and which pages are same-origin and thus
can reach in to each other. To make things as webby as possible though, I
think such URLs should be given a "real" domain, like app://
developer.com/myapp.html. This would be the domain of the developer, i.e. a
domain that the developer has to own. We would have to come up with some
mechanism for verifying this ownership though.

To make things more similar to how web pages normally work, we could allow
pages from app://developer.com/ to make network requests to
http://developer.com. I.e. the app would be allowed to open XMLHttpRequest
connections to http://developer.com/ <http://developer.com/.>myapi.cgi without
requesting any special privileges. Likewise <img>s and <video>s loaded from
http://developer.com would not be considered cross-origin for example for
the purposes of tainting when drawn into a <canvas>. This way most of the
code which would work for a website would work in a packaged app, except
that the packaged app would have to ensure to use absolute URLs when
wanting to connect to the website.

In order to keep applications isolated from each other (except through
explicit APIs like WebActivities) the app:// protocol always maps to
loading from the package that the load is initiated from. Consider a user
which has a facebook app and a google maps app installed. Whenever the
facebook app loads an app:// URL, we always look in the package which
contains the facebook app. If the resource isn't found there we return a
404 error. I.e. we never even look at the google maps package, even the
facebook app tries to load something like app://google.com/map.html, the
result is simply a 404. This also means that it's not a problem to install
two apps from google which both contains the same app://
google.com/library.js URL. Each app would simply load the library.js file
from its own package.


There are still lots of parts that we need to figure out. First of all we
need to define an exact format for the package. There are lots of formats
out there for signed packages, .jar which is commonly used by java, .xpi
which Firefox uses for addons, .crx used by Chrome, etc. We can either pick
an existing one, or design a new one. I'll explicitly declare it off topic
for this thread to come up with the specific format. Please start separate
threads about that.

We also need to come up with an update mechanism. One solution would be to
every now and then check the URL which we used to download the original
package to see if a new version is available. Another solution would be to
send a single request to the store enumerating all apps which we want to
check for updates for. That would allow for less traffic in the common case
of no apps needing any updates, but might be more complex to implement and
could have privacy implications. Again, this is off topic for this thread,
please start separate threads if you want to discuss this topic.


All in all this definitely means that trusted apps won't be as webby as
normal apps. However as long as we have the requirements around signing by
the store, an enforced CSP policy and a separate cookie jar, trusted apps
simply won't be very webby. Whether we zip the files up in an package and
deliver them the store for signing, or we deliver them through the store
through http, is a relatively small difference which only affects the
deployment of the app, not the development.

In the long run I definitely want to make trusted apps more "webby". Both
by changing our trusted apps work, and also by giving the web more
capabilities so that they can meet somewhere in the middle. But I think the
above proposal is a good way to start by doing something secure which will
give us experience and help us develop something better in the future.

/ Jonas
_______________________________________________
dev-webapps mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-webapps

Reply via email to