Closed Bug 852720 Opened 11 years ago Closed 11 years ago

Allow packaged apps to have an origin

Categories

(Core Graveyard :: DOM: Apps, defect)

x86
macOS
defect
Not set
normal

Tracking

(blocking-b2g:leo+, firefox22 wontfix, firefox23 wontfix, firefox24 fixed, b2g18 verified, b2g18-v1.0.0 wontfix, b2g18-v1.0.1 wontfix, b2g-v1.1hd fixed)

RESOLVED FIXED
mozilla24
blocking-b2g leo+
Tracking Status
firefox22 --- wontfix
firefox23 --- wontfix
firefox24 --- fixed
b2g18 --- verified
b2g18-v1.0.0 --- wontfix
b2g18-v1.0.1 --- wontfix
b2g-v1.1hd --- fixed

People

(Reporter: potch, Assigned: fabrice)

References

(Blocks 1 open bug)

Details

(Keywords: dev-doc-complete, Whiteboard: [LeoVB+])

Attachments

(1 file, 3 obsolete files)

Requiring CORS from anonymous origins can lead to security issues, and not having an origin causes iframe communication issues. Requiring SystemXHR to communicate with a single server is onerous. Could there be a way (likely based the URL of the minifest) to assign a real origin to a packaged app on installation? The results could then be treated/handled by the normal browser origin rules, and would operate more like the Web as a whole.
not having an origin also prevent us from using oauth services. https://groups.google.com/forum/?fromgroups=#!topic/mozilla.dev.webapps/EeflBoDrYfk
Yeah, I agree that we should figure something out here.

A tricky part is that the mozilla marketplace likely will want to host all packaged apps that they put in the store so that they have an opportunity to review them when they are updated. If they are hosted on the developer website that is no longer possible.

I would expect this to hold true for other marketplaces too.

That said, we're making exceptions to this rule for hosted apps, which we do allow developers to host themselves. So it's quite possible that we could make exceptions for packaged apps where the developer wants to self-host as to give the package an origin.


Another issue is that we need to enforce some sort of server opt-in to allowing an app package to be treated as being same-origin with the server that hosts it. There are lots of website that allow arbitrary uploading of files and if anyone could upload an app package to a 3rd party server and thus XSS it.

The opt-in could either be done by enforcing a mime type, or by looking for some other header. I know everyone hates both mimetypes and headers, but I don't see any other solution. Suggestions welcome.
Flags: sec-review?
I think we would need origins to do a Persona login from a packaged app too
(In reply to Kumar McMillan [:kumar] from comment #3)
> I think we would need origins to do a Persona login from a packaged app too

Hm, what does fireplace use?
(In reply to Fabrice Desré [:fabrice] from comment #4)
> (In reply to Kumar McMillan [:kumar] from comment #3)
> > I think we would need origins to do a Persona login from a packaged app too
> 
> Hm, what does fireplace use?

We don't (yet) because Persona in Fireplace doesn't presently work in the packaged app.
To be clear, you *can* use Persona right now, you just have to do things that are a bit scary because you have to communicate between a non-predictable origin (packaged app) and a network-based origin.
Sorry, I don't mean to shut down conversations, but I think there's general agreement that we would like to fix this bug.

The main question is how exactly to do it.
Add a field to the manifest:

"origin": "https://marketplace.mozilla.org"

It'll need to become a part of the review process for the reviewers to check to make sure that this isn't being abused.

It should only be respected for packaged apps (non-packaged web apps already have an origin). Your app shouldn't need to be privileged to use it (privileged apps already have systemXHR).
Some packaged apps won't be reviewed. How do we prevent origin hijacking and collisions?
Indeed. We support packaged apps to be installed by random 3rd parties. The only difference is that random 3rd parties can't sign the package.

So we could allow packages signed using a trusted certificate to have a origin property. But that means giving more special powers to mozilla which goes against the goal of building a platform that allows anyone to set up a store or self-host an app.
(In reply to Jonas Sicking (:sicking) from comment #10)
> So we could allow packages signed using a trusted certificate to have a
> origin property. 

I agree. This is the only solution I can think of. The authority that signs a packaged app is in a good position to assign a unique origin (within their realm).

> But that means giving more special powers to mozilla which
> goes against the goal of building a platform that allows anyone to set up a
> store or self-host an app.

Won't other parties be allowed to sign apps too? Limiting this feature to signing authorities is nice because it helps to avoid origin collisions and builds trust into the origin.
(In reply to Jonas Sicking (:sicking) from comment #10)
> So we could allow packages signed using a trusted certificate to have a
> origin property. But that means giving more special powers to mozilla which
> goes against the goal of building a platform that allows anyone to set up a
> store or self-host an app.

It also means that we're not solving anything for non-privileged packaged apps.

Does this "security" consideration actually protect against anything? An attacker could simply route XHRs through his own (CORSed) server and supply whatever origin/user agent/etc that he wants. Being able to set the origin on the device opens zero doors for the attacker, from what I can tell.
Might I suggest the following?

* A signed app may list as its origin an origin different from the origin that serves the package itself.
* An unsigned app can only list as its origin the origin from which the package is served. (The minifest can probably safely live elsewhere)
(In reply to Potch [:potch] from comment #13)
> Might I suggest the following?
> 
> * A signed app may list as its origin an origin different from the origin
> that serves the package itself.
> * An unsigned app can only list as its origin the origin from which the
> package is served. (The minifest can probably safely live elsewhere)

+1
I really don't want to grant more special powers for mozilla here. While additional parties in the future hopefully will be able to sign apps, it will never be the case that we can trust random new upstart stores or developers to sign apps an get special privileges.

If the solution we use only works for the mozilla marketplace because it has signing powers, then we're not creating a solution which enables other marketplaces.

(In reply to Potch [:potch] from comment #13)
> * An unsigned app can only list as its origin the origin from which the
> package is served. (The minifest can probably safely live elsewhere)

This doesn't solve the problem described in comment 2. If I want to attack dropbox I simply create a packaged file which says "origin: https://dropbox.com" and then upload it to dropbox server.
(In reply to Jonas Sicking (:sicking) from comment #15)
> This doesn't solve the problem described in comment 2. If I want to attack
> dropbox I simply create a packaged file which says "origin:
> https://dropbox.com" and then upload it to dropbox server.

This is false (at least in the case of Dropbox). Dropbox files are hosted on subdomains:

https://dl-web.dropbox.com
https://photos-1.dropbox.com

Dropbox never serves any content from its second-level domain. This means that you couldn't use the origin field to muck around with a user's Dropbox account. The same goes for Github (and GH pages), since they're always on subdomains.

Frankly, if a service is allowing user-uploaded zip files to be hosted from their primary domain, they've got security issues that go far beyond us letting a developer make requests to their domain as if the request was coming from one of their own pages. If a developer can upload a ZIP file, why not HTML files and simply iframe to them (which would probably be easier in some ways, seeing as you wouldn't even need to make a packaged app and skip a lot of the review process)?
I really like Potch's suggestion. It strikes a very nice balance. I agree with Matt that web sites already have to be super careful about user-contributed content at their main origin (content-type confusion, etc.)

I want to emphasize that the current situation lends itself to very insecure behavior for packaged apps that need to do any kind of authentication flow, using either Facebook, Google, or Persona.

The issue is that the packaged app has no predictable origin, which means that either:

(a) users have to agree to things like "log in to app://<random-guid>?", or

(b) the app needs a hosted component at its homebase origin to mediate. In and of itself that's not a problem, but then the hosted component can't really be sure it's talking to its packaged counterpart.

IOW, not a theoretical issue, there's a real problem here. Following Potch's recommendation is probably a good compromise.
(In reply to Matt Basta [:basta] from comment #16)
> (In reply to Jonas Sicking (:sicking) from comment #15)
> > This doesn't solve the problem described in comment 2. If I want to attack
> > dropbox I simply create a packaged file which says "origin:
> > https://dropbox.com" and then upload it to dropbox server.
> 
> This is false (at least in the case of Dropbox). Dropbox files are hosted on
> subdomains:
> 
> https://dl-web.dropbox.com
> https://photos-1.dropbox.com

That just means that you can launch XSS attacks against those origins instead. Likely that means that I could upload an app to dropbox and then read any data stored in dropbox from anyone that installs the app.

> Frankly, if a service is allowing user-uploaded zip files to be hosted from
> their primary domain, they've got security issues that go far beyond us
> letting a developer make requests to their domain as if the request was
> coming from one of their own pages. If a developer can upload a ZIP file,
> why not HTML files and simply iframe to them (which would probably be easier
> in some ways, seeing as you wouldn't even need to make a packaged app and
> skip a lot of the review process)?

Currently "all" that dropbox needs to do is to ensure that no content from their website is served with a "text/html" mime type. IE used to not enforce this mimetype very strictly and instead use sniffing to detect HTML pages. This lead to all sorts of websites getting hacked because of exactly this problem. Since then they have added various heuristics as well as special headers that websites need to set in order to secure themselves.

Another issue is that in many cases websites allow uploading images of various formats in order to attach pictures/avatars of themselves. However it has happened many times in the past that security researchers have been able to craft files that both pass as valid images, as well as valid files of other formats.

All of this is why we strictly enforce the mime type for the jar: protocol. I.e. you can't link to jar:http://example.com/file.zip!page.html unless file.zip is served with "application/java-archive" as mimetype. See

https://developer.mozilla.org/en-US/docs/Security_and_the_jar_protocol

Websites do allow users to upload arbitrary content, that's just a reality that we have to live in. I wish it wasn't so, but unfortunately it is.

Any mechanism that is proposed which relies on servers not hosting app files is unfortunately a no-go.
(In reply to Ben Adida [:benadida] from comment #17)
> I really like Potch's suggestion. It strikes a very nice balance. I agree
> with Matt that web sites already have to be super careful about
> user-contributed content at their main origin (content-type confusion, etc.)

The one thing that could be confusing from a developer's perspective if we were to add an "origin" property is the clarity that this only applies to signed packaged apps. Hosted apps have a concept of an origin, but there exists an "origin" manifest property. Couldn't there be confusion here?

I generally feel like there's two concepts getting confused here. The concept of where the app was derived from vs. what we're actually calling the app's origin it's running on. But I wonder if that's the right thing users would actually trust. Say box.com indicates in their app their origin is box.com. A user then sees log into...what? box.com could be confusing to indicate here, cause it begins to confuse the concept of being in hosted content vs. content running locally.

I did always wonder if it was worthwhile to consider having an app origin for a packaged app to exchange UUID for something a user would understand. That would eliminate the need for another manifest property and integrate well into our platform. Is there a possible exchange route for UUID --> something worthwhile here?

> 
> I want to emphasize that the current situation lends itself to very insecure
> behavior for packaged apps that need to do any kind of authentication flow,
> using either Facebook, Google, or Persona.
> 
> The issue is that the packaged app has no predictable origin, which means
> that either:
> 
> (a) users have to agree to things like "log in to app://<random-guid>?", or

FWIW, for permission prompts, we solved [a] by indicating the "app name" instead of app://<random-guid> for v1. Why wouldn't that work here?
Bear in mind that apps run with their own cookie jars, meaning that an XSS attack doesn't mean anything. If the attacker has the user's credentials to manipulate the site in some way, it means that the user has already been phished and the attacker could execute their shenanigans from any HTTP-capable script (client side or otherwise). The attacker's only benefit to having this access is to make HTTP requests to a host en masse via all of the app's installations.

At this point, we're not trying to solve user privacy anymore (since user privacy is not at stake), we're delving into the realm of preventing apps which function as botnets from finding their way onto users' devices. We'll never solve this problem (there's no such thing as a modern, malware-free platform).

In short, the attacker needs to have:
- Found a site which hosts user-uploaded content on the same domain (not subdomain) as their web application (of which Dropbox, still, is not among)
- Gotten users to install the packaged app outside of the Marketplace

And for all of that work, they have only gained the ability to make HTTP requests to the original domain without any sort of pre-existing session. They could do the same thing from:
- Heroku's free tier
- AWS's free tier
- their home Comcast connection and a Rasberry Pi
- the computers at their local library
- a botnet they purchased time on from some teenager in China
- etc.

At the end of the day, they *still* haven't accessed user data, and IMHO that's good enough for us to ship.
(In reply to Jason Smith [:jsmith] from comment #19)
> (In reply to Ben Adida [:benadida] from comment #17)
> > I really like Potch's suggestion. It strikes a very nice balance. I agree
> > with Matt that web sites already have to be super careful about
> > user-contributed content at their main origin (content-type confusion, etc.)
> 
> The one thing that could be confusing from a developer's perspective if we
> were to add an "origin" property is the clarity that this only applies to
> signed packaged apps. Hosted apps have a concept of an origin, but there
> exists an "origin" manifest property. Couldn't there be confusion here?

The vast majority of developers don't need this property, and we can note that it's only for use by packaged apps (which don't have a "real" origin).

> it begins to confuse the concept of being in hosted
> content vs. content running locally.

The user shouldn't know the difference. Allowing the app to supply an origin eliminates the need for the user to know how/why things work.

> I did always wonder if it was worthwhile to consider having an app origin
> for a packaged app to exchange UUID for something a user would understand.

This is, in effect, what's being asked for. The UUID is the origin, and we're looking for a way to get something that's useful for the developer and understandable for the user. As it stands now, a packaged app is *less* useful than a hosted app because packaged apps can't access servers that don't implement CORS: should we be telling developers to figure out how to CORS their app or that they can add one or two lines of code to their app and things work the way they'd expect?

> FWIW, for permission prompts, we solved [a] by indicating the "app name"
> instead of app://<random-guid> for v1. Why wouldn't that work here?

Consider Persona, which is web content and doesn't have access to the app's name.
I still like this idea the best:

(In reply to Potch [:potch] from comment #13) 
> * A signed app may list as its origin an origin different from the origin
> that serves the package itself.
> * An unsigned app can only list as its origin the origin from which the
> package is served. (The minifest can probably safely live elsewhere)

To address some of comment #2:
- the XSS risk doesn't seem any worse than today's web so I think it's moot
- how does an app signer allow devs to specify a domain without stealing other people's domain? Perhaps it doesn't allow custom domains at all. The signer could dictate domains always in the form of yourapp.signer-designated-domain.com
(In reply to Kumar McMillan [:kumar] from comment #22)
> To address some of comment #2:
> - the XSS risk doesn't seem any worse than today's web so I think it's moot

Can you explain what you mean by this?

The fact that anyone can run script on any website which allows arbitrary uploads is absolutely a new thing and definitely "worse" than today's web.

I do agree that the fact that apps run in a separate cookie jar has the potential to alleviate the concerns here quite a lot. However it would still be a huge change from the current state of things where we generally rely on that code from origin http://evil.com can't inject code into origin https://bunnies.com.

With this change we would say that we do allow such injection, but the code always runs in a separate cookiejar.

My main concern is that there's a big risk that it'll limit other mechanisms that we might want to build in the future. For example we've discussed creating an inter-app-communication API which allows apps from the same origin to directly send messages to each other. That would likely not work under this proposal since the origin of an app has lost most of it's trust label.
(In reply to Jonas Sicking (:sicking) from comment #23)
> My main concern is that there's a big risk that it'll limit other mechanisms
> that we might want to build in the future. For example we've discussed
> creating an inter-app-communication API which allows apps from the same
> origin to directly send messages to each other. That would likely not work
> under this proposal since the origin of an app has lost most of it's trust
> label.

As it stands packaged apps effectively have no origin, so that proposal is dead in the water unless there's a way to give a packaged app an origin. I'd go so far as to say that those plans are dependent on a positive resolution of this bug. Because frankly, that's kind of a not-so-useful feature for web apps since application state is on the server and not on the client.

Besides the obvious fact that we currently limit devices to one app per origin (still. still.), it should be a huge note above that API's documentation that makes developers aware of the potential risks and makes sure they're not serving user-uploaded content from the same domain as their application.

I'd be open to hearing other, less risky--for lack of a better phrase--suggestions, but I think Potch's idea is perhaps the best we've got. If the worst we have to worry about is that someone can make HTTP requests (and technically not execute code, it's just HTTP requests) to a server which is improperly configured to serve user-uploaded content from the same origin as the application via an app that our users have consciously installed and run, then I think we're in pretty good shape.
(In reply to Jonas Sicking (:sicking) from comment #23)
> 
> My main concern is that there's a big risk that it'll limit other mechanisms
> that we might want to build in the future. For example we've discussed
> creating an inter-app-communication API which allows apps from the same
> origin to directly send messages to each other. That would likely not work
> under this proposal since the origin of an app has lost most of it's trust
> label.

I still reject your assertion that allowing a packaged app served from an origin to specify that same origin breaks anything from a security standpoint.

As far as concerns about giving Mozilla special powers, the whole notion of 'certified' and 'signed' tiers of apps has already done that to such a supreme degree that we might as well let un-blessed packaged apps have a bone here. Which is to say, security has already rained on this parade, let's at least hand out ponchos.
(In reply to Jonas Sicking (:sicking) from comment #23)
> (In reply to Kumar McMillan [:kumar] from comment #22)
> > To address some of comment #2:
> > - the XSS risk doesn't seem any worse than today's web so I think it's moot
> 
> Can you explain what you mean by this?
> 
> The fact that anyone can run script on any website which allows arbitrary
> uploads is absolutely a new thing and definitely "worse" than today's web.

ok, I think I understand this better. Maybe we do need to enforce a new mime type for served packaged apps then.
(In reply to Matt Basta [:basta] from comment #21)
> (In reply to Jason Smith [:jsmith] from comment #19)
> > (In reply to Ben Adida [:benadida] from comment #17)
> > > I really like Potch's suggestion. It strikes a very nice balance. I agree
> > > with Matt that web sites already have to be super careful about
> > > user-contributed content at their main origin (content-type confusion, etc.)
> > 
> > The one thing that could be confusing from a developer's perspective if we
> > were to add an "origin" property is the clarity that this only applies to
> > signed packaged apps. Hosted apps have a concept of an origin, but there
> > exists an "origin" manifest property. Couldn't there be confusion here?
> 
> The vast majority of developers don't need this property, and we can note
> that it's only for use by packaged apps (which don't have a "real" origin).
> 
> > it begins to confuse the concept of being in hosted
> > content vs. content running locally.
> 
> The user shouldn't know the difference. Allowing the app to supply an origin
> eliminates the need for the user to know how/why things work.

True, but we solved this problem with giving the app name. The origin I think goes a step in a direction I wouldn't agree with - it actually introduces the confusion of the notion of thinking something is remote when in fact it's local.

As an additional note to everyone on this discussion - keep in mind that we do have to be careful "how" we introduce an origin to these packaged apps. In testing, there's some cases where we realized the one app per origin limitation did affect packaged apps, so be mindful about how we introduce the origin concept such that limitation doesn't set us back for how developers create their packaged apps.
/me notes that assigning a non-app:// origin to a packaged app will lead to some issues to just load the app resources from the package.
(In reply to Fabrice Desré [:fabrice] from comment #28)
> /me notes that assigning a non-app:// origin to a packaged app will lead to
> some issues to just load the app resources from the package.

Interesting. So maybe a tweak on potch's proposal that might make Jonas happy too: let https://foobar.example.com set its packaged app origins to be app://foobar.example.com.

That gives us a separate origin, which is good for isolation.

It gives us an app:// origin, which addresses Fabrice's problem.

And it gives us a *predictible* origin so we can do postMessage() and redirects and what not.
(In reply to Ben Adida [:benadida] from comment #29)
> (In reply to Fabrice Desré [:fabrice] from comment #28)
> > /me notes that assigning a non-app:// origin to a packaged app will lead to
> > some issues to just load the app resources from the package.
> 
> Interesting. So maybe a tweak on potch's proposal that might make Jonas
> happy too: let https://foobar.example.com set its packaged app origins to be
> app://foobar.example.com.
> 
> That gives us a separate origin, which is good for isolation.
> 
> It gives us an app:// origin, which addresses Fabrice's problem.
> 
> And it gives us a *predictible* origin so we can do postMessage() and
> redirects and what not.

That is very nice!
I'm a little bit confused about what's the problem exactly here. Assuming we introduce a synthetic origin to packaged apps, somehow. And thus, for app://whatever we know that it's origin is http[s]://otherwhatever. What will this allow exactly from a security point of view?

* I assume it'll allow the app XHRing to http[s]://otherwhatever without requiring systemXHR.

And?...

* What happens with CSP? Will the app be able to load and execute scripts from http[s]://otherwhatever?
* Will the app be able to access other iframes from the same "origin"?
* Will iframes from the same origin be able to access the app iframes?
* ...? (I'm pretty sure I've not covered all the things that fall under the same-origin umbrella)

If all the problem is XHR, then for privileged apps this is a non issue: We already allow them to request systemXHR, and if the problem is that systemXHR is too wide (which it might be) then the easier (and securer) solution will be to allow the app to restrict the list of domains it needs access to. 

For non privileged apps... wouldn't it be enough to pass the base64(SHA-1(installed-from)) as the origin header if the real origin is app://whatever? That would give a predictable identifier for the app developer to use CORS effectively (even on a per-app basis allowing several apps to be served from the same domain). And it would be (more or less, and a little less than more :) ) in line with [1], point 3.

[1] http://tools.ietf.org/html/rfc6454#section-4
(In reply to Antonio Manuel Amaya Calvo from comment #31)
> I'm a little bit confused about what's the problem exactly here. Assuming we
> introduce a synthetic origin to packaged apps, somehow. And thus, for
> app://whatever we know that it's origin is http[s]://otherwhatever. What
> will this allow exactly from a security point of view?
> 
> * I assume it'll allow the app XHRing to http[s]://otherwhatever without
> requiring systemXHR.

No, I don't think we need that. We could truly rely on app://<whatever> and https://<whatever> being different origins.

The key point is that the packaged app origin is *stable* and *publicly known*. That means that https://<whatever> can receive postMessage() from app://<whatever>, or redirect to app://<whatever>, and know it's hitting the right code.

> * What happens with CSP? Will the app be able to load and execute scripts
> from http[s]://otherwhatever?

no.

> * Will the app be able to access other iframes from the same "origin"?

no. The meaning of "origin" wouldn't change.

> * Will iframes from the same origin be able to access the app iframes?

no.

The goal is not to weaken same-origin, the goal is to have a stable and public origin for the packaged component so that redirect flows (oauth, openid) and origin-dependent UIs (openid, oauth, Persona) can function properly, and so that packaged apps can communicate safely with their hosted counterpart via postMessage and/or redirects.
My goal in filing this bug was that packaged apps would more closely resemble the communication abilities and permissions that one would have with an appcached hosted app. Ben's adaptation of my initial proposal certainly moves things in that direction.
(In reply to Ben Adida [:benadida] from comment #32)
> 
> The key point is that the packaged app origin is *stable* and *publicly
> known*. That means that https://<whatever> can receive postMessage() from
> app://<whatever>, or redirect to app://<whatever>, and know it's hitting the
> right code.
> 

Ok, I think I get it now. The oauth problem isn't caused because the origin isn't known, it's caused because you cannot redirect from otherprotocol: to app: 
Even app://app1 cannot redirect to app://app2 (see bug 773886). 

So if doing

window.opener.postMessage(result, "app://*") // Matches if the protocol is app...

were allowed we would be covered for the security problem that [1] talked about. We can't do postMessages cross app since we don't get the window object to it, and if a window inside an app has the app protocol then it's the correct app... cannot be otherwise.

A possible fix for the redirects-inside-an-app could be relaxing the restriction in bug 773886 to allow a window to navigate to an app that has the same origin than its opener. That way redirecting from https://something to app://otherthing would work if and only if the opener of the window holding https://something was app://otherthing. With that (and assuming the oauth service actually supported redirecting to app://) the problem would be fixed even without knowing a priori the actual app:// URI.

And for the systemXHR problem that c0 talked about... well, that was my previous answer :)


[1] https://groups.google.com/forum/?fromgroups=#!topic/mozilla.dev.webapps/EeflBoDrYfk
(In reply to Antonio Manuel Amaya Calvo from comment #34)
> 
> Ok, I think I get it now. The oauth problem isn't caused because the origin
> isn't known, it's caused because you cannot redirect from otherprotocol: to
> app: 

No that's not it. 

The problem is that the app:// has an origin that is different on each device and unpredictable / unrelated to its publisher.

> window.opener.postMessage(result, "app://*") // Matches if the protocol is
> app...

That would not be very secure. I want to message a specific app, not any app that happened to embed me in an IFRAME.

For example, when marketplace becomes a packaged app, it may embed, in an IFRAME, some resources from its hosted component, and use postMessage() to communicate with it. How does the hosted component know that the message is coming from the right packaged app? Without a uniquely-namespaced identity that everyone agrees on, it's an unauthenticated channel, which is problematic.

(Another issue is that the origin is often used as part of UIs like "do you want to log into foobar.com?" With GUID origins, that becomes useless.)
I think we could create a setup where the app still has a "app://..." URL when it comes to loading resources, but that origin is considered same-origin with a "http://..." or "https://..." URL. I.e. iframing or creating XHR requests from the app-URL to the http(s)-URL would be treated like a same-origin request

(In reply to Potch [:potch] from comment #25)
> I still reject your assertion that allowing a packaged app served from an
> origin to specify that same origin breaks anything from a security
> standpoint.

I'd love to hear which point you specifically think is wrong.

> As far as concerns about giving Mozilla special powers, the whole notion of
> 'certified' and 'signed' tiers of apps has already done that to such a
> supreme degree that we might as well let un-blessed packaged apps have a
> bone here. Which is to say, security has already rained on this parade,
> let's at least hand out ponchos.

I don't understand what you are saying here. What I'm saying is that I'd like to find a solution which also works for packaged apps coming from other app-stores rather than relying on signing. *That* would be tossing them a poncho.

Saying "lets solve things by relying on signing" is exactly the reverse of raining even more on their parade and forcing people to use the mozilla appstore.

And no, I don't think creating a solution which isn't secure is helping anyone. Especially not small developers which don't know all the intricacies of what they need to do in order to secure their webserver.

So far mimetypes or other headers is the only solution proposed so far that would actually work. Feel free to suggest other ones but simply ignoring security issues is not very productive.
Summary: Allow packaged apps to have an origin. → Allow packaged apps to have an origin
(In reply to Ben Adida [:benadida] from comment #35)
> (In reply to Antonio Manuel Amaya Calvo from comment #34)
> > 
> > Ok, I think I get it now. The oauth problem isn't caused because the origin
> > isn't known, it's caused because you cannot redirect from otherprotocol: to
> > app: 
> 
> No that's not it. 

I'm sorry but yes, that's it. You cannot do redirects even to certified apps which DO have a well known and public URI. And you cannot do it because loading or redirecting to an app:// protocol from any other protocol is not allowed. Again, see bug 773886. That's why the communications app uses an intermediate server to do the Oauth, even when its url is always app://communications.gaiamobile.org.

> The problem is that the app:// has an origin that is different on each
> device and unpredictable / unrelated to its publisher.
> 
> > window.opener.postMessage(result, "app://*") // Matches if the protocol is
> > app...
> 
> That would not be very secure. I want to message a specific app, not any app
> that happened to embed me in an IFRAME.

Ok, fair enough, I was talking about the Oauth case, for which, honestly, considering you have to embed the client secret on the app controlling who you're communicating with, more than it being an app (and even that) is like locking the stable door after the horse has already bolted.

> 
> For example, when marketplace becomes a packaged app, it may embed, in an
> IFRAME, some resources from its hosted component, and use postMessage() to
> communicate with it. How does the hosted component know that the message is
> coming from the right packaged app? Without a uniquely-namespaced identity
> that everyone agrees on, it's an unauthenticated channel, which is
> problematic.

Can't this just be solved as well by my XHR proposal before? If the origin header is derived from the install-from then the server can verify the origin. And for postMessages, if the origin is correct then the app can just pass it's own URI to the server and thus establish a 'secure' channel.

So it would go:

app://{uuid} -> Load http://myserver.com?myURIIs=app://{uri}

Gecko adds an origin header:
origin: base64(SHA-1(full_install_from_uri))

Server: 
* Verifies than the origin is correct (the app is the one installed from where I left my packaged app)
* If it is, then the URI passed is valid. Use that on the postMessages to my hearts content.

Origin must be based on the whole URI to avoid running into problems when hosting the packages on servers the developer don't control completely. Like an store. Or dropbox. Or Mega. 

And it should be the install-from and *not* a field from the manifest because the manifest is only trustable on privileged apps. 


Note that this still won't make redirects work, because you cannot load an app:// from an http(s):// even if you know the URI as I stated before.

> 
> (Another issue is that the origin is often used as part of UIs like "do you
> want to log into foobar.com?" With GUID origins, that becomes useless.)
(In reply to Antonio Manuel Amaya Calvo from comment #37)
> (In reply to Ben Adida [:benadida] from comment #35)
> > (In reply to Antonio Manuel Amaya Calvo from comment #34)
> > > 
> > > Ok, I think I get it now. The oauth problem isn't caused because the origin
> > > isn't known, it's caused because you cannot redirect from otherprotocol: to
> > > app: 
> > 
> > No that's not it. 
> 
> I'm sorry but yes, that's it.

I'm sorry Antonio, I didn't mean to say you were wrong in your description, only that this wasn't the point I was trying to make.

> Ok, fair enough, I was talking about the Oauth case, for which, honestly,
> considering you have to embed the client secret on the app controlling who
> you're communicating with, more than it being an app (and even that) is like
> locking the stable door after the horse has already bolted.

Right, I agree.

But for apps that do have a server-side component like marketplace, you can use the hosted component to follow the safe OAuth path, or do OpenID. Or Persona assertion verification, of course. All of these require some user-understandable origin, and to do them safely, since you need a mediator, securing the packaged-to-hosted communication channel by identifying the packaged component consistently would be very helpful.

> app://{uuid} -> Load http://myserver.com?myURIIs=app://{uri}
> 
> Gecko adds an origin header:
> origin: base64(SHA-1(full_install_from_uri))

Why not just use the origin header in the way it was intended, with an actual origin? And if we do that, aren't we effectively assigning an origin to the app? Then let's just assign that origin and let the rest of the web stack work unimpeded!
(In reply to Jonas Sicking (:sicking) from comment #36)
> 
> (In reply to Potch [:potch] from comment #25)
> > I still reject your assertion that allowing a packaged app served from an
> > origin to specify that same origin breaks anything from a security
> > standpoint.
> 
> I'd love to hear which point you specifically think is wrong.

I disagree that in this case serving a zip that contains html which can act as if it was from that server's origin (what the proposal is) is less secure than a server that serves html that can act as if it was from that server's origin (which is what every webpage on the internet is).

> 
> > As far as concerns about giving Mozilla special powers, the whole notion of
> > 'certified' and 'signed' tiers of apps has already done that to such a
> > supreme degree that we might as well let un-blessed packaged apps have a
> > bone here. Which is to say, security has already rained on this parade,
> > let's at least hand out ponchos.
> 
> I don't understand what you are saying here. What I'm saying is that I'd
> like to find a solution which also works for packaged apps coming from other
> app-stores rather than relying on signing. *That* would be tossing them a
> poncho.
> 
> Saying "lets solve things by relying on signing" is exactly the reverse of
> raining even more on their parade and forcing people to use the mozilla
> appstore.
> 
> And no, I don't think creating a solution which isn't secure is helping
> anyone. Especially not small developers which don't know all the intricacies
> of what they need to do in order to secure their webserver.
> 
> So far mimetypes or other headers is the only solution proposed so far that
> would actually work. Feel free to suggest other ones but simply ignoring
> security issues is not very productive.

I think we might actually be violently agreeing with each other on this point :) I was trying to say that making a solution that requires signing is a non-solution to this problem, and that it should work for unprivileged packaged apps (though it might be nice to let signers have additional privileges). My main sticking point is that the .zip is somehow less secure than existing web content. If it is, then mime-type seems to be the way to go.
(In reply to Potch [:potch] from comment #39)
> My main sticking point is that the .zip is somehow less secure
> than existing web content.

It's not. But we are enforcing mime types for HTML files, that's what make them safe. I'm just saying that we need to do the same thing for webapp packages.
Flags: sec-review? → sec-review?(ptheriault)
(In reply to Ben Adida [:benadida] from comment #38)
> (In reply to Antonio Manuel Amaya Calvo from comment #37)
> > app://{uuid} -> Load http://myserver.com?myURIIs=app://{uri}
> > 
> > Gecko adds an origin header:
> > origin: base64(SHA-1(full_install_from_uri))
> 
> Why not just use the origin header in the way it was intended, with an
> actual origin? And if we do that, aren't we effectively assigning an origin
> to the app? Then let's just assign that origin and let the rest of the web
> stack work unimpeded!

Sorry for the delay, this somehow fell from my queue. We could use just 
origin: anOrigin

where anOrigin is the origin derived from the install_from_uri. But that wouldn't solve the problem of serving multiple apps from a single install origin (as in a store). Using the full URI (as opposed to just the protocol + domain) would solve that. 

And it has to be (or rather should be) the install uri and not something extracted from the manifest because the install_uri can be trusted to have the real value since it can be filled by the OS, while whatever is read from the manifest can be trusted only if the application is signed.
We're talking about how to use oauth in bug 852848 as well.  Bug 852848 comment 27 is my proposal for how to make that work.  I'm not positive it's relevant here, but it seems like it is...

I'll cc you all so you can read it.
This is what the Marketplace needs to do to authenticate with Persona:

https://github.com/mozilla/fireplace/blob/master/hearth/media/js/login.js

Notice the window.postMessage calls.

This is a shameful hack and I feel bad that we need this in our codebase(s). Unfortunately there's no other option for us, or any other packaged app developer.
Following up on Matt's point... we're going to see lots more of these "shameful" hacks if we don't have stable origins for our apps, packaged or otherwise.

Taking into account Jonas's concerns (delivering packaged apps with a brand new content-type), can we agree to set a real, stable origin for packaged apps as soon as possible? Either using potch's suggestion, my tweak to it, or some other tweaked version if that helps?
Blocks: 867265
Blocks: 867479
I've talked this over with various people lately and so wanted to document my thoughts:

While I'm in general not a fan of solutions that rely on package signing, since that means that those solutions force developers to distribute apps through the mozilla marketplace, there are some mitigating factors here.

The main use cases for packaged apps that I've heard of so far are:

* Privileged apps. Have to be packaged since the security model relies on signature
  verification.
* Developers that don't want to rely on our existing AppCache in order to support
  offline. Either due to the AppCache spec being crappy, or because of the bad
  performance of our implementation.
* Developers that don't want to manage a webserver in order to distribute an app.

The first group relies on package signing *anyway*, so supporting origins for these apps through signing doesn't impose any new problems.

The second group should ideally be a passing problem. We've started work on coming up with a new appcache spec and I'm pretty confident that we can solve this. So there's actually a slight advantage here of relying on signing since it means that we don't have to add permanent features to the web platform.

That leaves the third group. It's arguably the case that a developer shouldn't really get to have a "real" origin if they don't want to own a website. Arguably they don't really need it since there's no website that they need to do "same-origin" communication with.

However that's not the whole truth. Even if you don't have a web server, you might still want to do communication with third parties, for example using OAuth. Such scenarios would still find it very useful to have a reliable origin for the packaged app.

One potential solution here would be some form of developer signing. Ideally using a cert that shows that they are the owner of the domain. I *think* CA certs could sort of do this. However Brian Smith tells me that CA certs usually are only valid for SSL use and so it might be an abuse to use them for app package signing.

I think this is an area that needs more investigation.

In the meantime, it seems like solving the first two groups by relying on "normal" (signed by trusted store) signed apps.
I think that we can reduce the priority of the third use case given that you can always imagine that web services will offer to host applications for people who doesn't want to worry about that. Those services could definitely have an URL like developer.example.com/application/ (though we need to support multiple apps per origin). If there is a need that can be satisfied, people will likely try to make a business around it ;)
On another thread, we've just discovered that pre-installed apps (like Marketplace), can get origins like app://marketplace.firefox.com. So why don't we, conservatively, start with that solution for pre-installed apps, see how it works, and then expand the functionality to other packaged apps in 1.1/1.2?
(In reply to Ben Adida [:benadida] from comment #47)
> On another thread, we've just discovered that pre-installed apps (like
> Marketplace), can get origins like app://marketplace.firefox.com. So why
> don't we, conservatively, start with that solution for pre-installed apps,
> see how it works, and then expand the functionality to other packaged apps
> in 1.1/1.2?

That sounds fine to me from the quality perspective in terms of risk vs. schedule vs. known issues.
So we are ok with not supporting persona in 3rd party packaged apps? That looks terrible to me. We already single out the marketplace as the only source of privileged apps, but this is even worse. Please tell me I misunderstood.
(In reply to Ben Adida [:benadida] from comment #47)
> On another thread, we've just discovered that pre-installed apps (like
> Marketplace), can get origins like app://marketplace.firefox.com. So why
> don't we, conservatively, start with that solution for pre-installed apps,
> see how it works, and then expand the functionality to other packaged apps
> in 1.1/1.2?

1.1/1.2? :( Guess developers won't be able to test paid packaged apps till then, so there won't be any (at least that verify their receipts).
(In reply to Fabrice Desré [:fabrice] from comment #49)
> So we are ok with not supporting persona in 3rd party packaged apps? That
> looks terrible to me. We already single out the marketplace as the only
> source of privileged apps, but this is even worse. Please tell me I
> misunderstood.

Technically, I'm not actually okay with this in it's limitation definition. The problem I have is the fact that we're simply out of time for Mozilla-specific needs in 1.01. Conversations I've had with partners have revealed such items as:

1. 5/10 is a *final* date for anything Mozilla related landed in 1.01
2. We have known limitations already for Mozilla needs that have a similar severity as this bug that are being handled in 1.1. Examples include - h264 in web content, input file support - both of which are very core features of the mobile web. Knowing this, it'll make a tough argument to argue this into 1.01 unless the solution proposed for 1.01 is low risk.

I'm putting needinfo though to get a final call from the product team so that we can settle on what we're doing in each release here.
Flags: needinfo?(ffos-product)
(In reply to Nick Desaulniers [:\n] from comment #50)
> (In reply to Ben Adida [:benadida] from comment #47)
> > On another thread, we've just discovered that pre-installed apps (like
> > Marketplace), can get origins like app://marketplace.firefox.com. So why
> > don't we, conservatively, start with that solution for pre-installed apps,
> > see how it works, and then expand the functionality to other packaged apps
> > in 1.1/1.2?
> 
> 1.1/1.2? :( Guess developers won't be able to test paid packaged apps till
> then, so there won't be any (at least that verify their receipts).

If the issue was resolved in 1.1, then developers would at least be able to test paid packaged apps on 1.1 builds. So I'm not sure if that's a cut and dry blocker to testing at all - it's a blocker to testing on 1.01 build.
I'm bouncing this into the leo bucket first for a blocking call on 1.1. One of these blocking flags needs to be set here, but don't know which one until the product team makes a decision.
blocking-b2g: --- → leo?
Can someone at least start working on this? I think it's been unanimously agreed that we need it, and the last thing we need is for 1.1 to roll around and we're caught with our pants down because we're still taking about which version it should end up in.
I agree with the sentiment that we should get moving on this in general, I just know that the pressure for 1.0.1 is immense, and we have to cut difficult corners.

I do want to correct Fabrice's wording, it's important to be precise: Persona works just fine in any packaged app today, it's just that you get a UI that makes no sense because the packaged app has no sensible origin. And if you have a hosted server, you have to request systemXHR or do unsafe postMessage'ing to communicate with it. But that's because of the origin problem, it has nothing to do with Persona.

Let's be very clear that, the moment we skip true predictable and meaningful origins, we create a host of problems across the board for web developers. That it manifests in the Persona flow is just one of many symptoms of this underlying problem.
It's not just testing of paid packaged apps. The verification of paid packaged app receipts will have a security hole, unless we do a workaround for this.
I think we should start by allowing signed apps to have an origin.

Beyond that I think I don't still have a good enough understanding of the use cases to have an opinion. I.e. I don't understand the OAuth or Persona protocols to really understand how to solve the problems.

Simply slapping an origin on packaged apps and hope that that resolves things doesn't feel like a very attractive approach to me.

It'd help me at least to have a meeting to talk through the various issues and potential solutions. Not sure if others feel the same.
(In reply to Jonas Sicking (:sicking) from comment #57)
> I think we should start by allowing signed apps to have an origin.

Instead of checking for signed apps, I would opt for allowing it to privileged apps instead; as signing really makes debugging a lot harder. There is a manageable amount of privileged apps in the Marketplace, so minor impact.
(In reply to Harald Kirschner :digitarald from comment #58)
> Instead of checking for signed apps, I would opt for allowing it to
> privileged apps instead; as signing really makes debugging a lot harder.
> There is a manageable amount of privileged apps in the Marketplace, so minor
> impact.

Currently an application is privileged iif it is signed.
Attached patch patch (obsolete) — Splinter Review
This patch honors a "app_origin" property in manifests (the one in the zip), for signed privileged apps. If you are not running an official build, you can test that with non-privileged apps also.

Note that the origin must be app://foobar, not http(s)://foobar. We don't solve any use case that needs systemXHR here, and if we want to address that we should do that in a followup.
Assignee: nobody → fabrice
(In reply to Mounir Lamouri (:mounir) from comment #59)
> (In reply to Harald Kirschner :digitarald from comment #58)
> > Instead of checking for signed apps, I would opt for allowing it to
> > privileged apps instead; as signing really makes debugging a lot harder.
> > There is a manageable amount of privileged apps in the Marketplace, so minor
> > impact.
> 
> Currently an application is privileged iif it is signed.

No. An app must be signed to be privileged, but a signed app is not necessarily privileged. In particular, all packaged apps from the Mozilla Marketplace are signed but not all of them are privileged.

(In reply to Fabrice Desré [:fabrice] from comment #60)
> Note that the origin must be app://foobar, not http(s)://foobar. We don't
> solve any use case that needs systemXHR here, and if we want to address that
> we should do that in a followup.

It is important to note that there seems to be a requirement for global uniqueness of the app origin. For example, if Developer A develops an app with origin app://foobar, then we must ensure that Developer B never develops an app with origin app://foobar, regardless of what marketplace it is (even ones we don't control) and regardless of how much time has passed (if any) between Developer A and Developer B developing their apps.

Further, we must ensure that the explicit app_origin using in the form of the unique IDs that we would auto-generate if it were missing, for the same reasons.

IMO, if the only requirement for B2G v1 is that the origin must be stable across different installations of the same app, then we could just use something like app://marketplace.firefox.com/{ID}, where {ID} is the unique identifier that we generated in ids.json for the app.
(In reply to Brian Smith (:bsmith) from comment #61)
> IMO, if the only requirement for B2G v1 is that the origin must be stable
> across different installations of the same app, then we could just use
> something like app://marketplace.firefox.com/{ID}, where {ID} is the unique
> identifier that we generated in ids.json for the app.

Origins don't include paths, and if we're coming up with crazy new "origins" that don't follow existing conventions and blaze their own trails then we're only making the problem worse.

Additionally, we should not be making the platform dependant on the Marketplace. A long-term goal is to support 3rd party marketplaces, and adding more and more dependencies on our own marketplace only increases the burden on our future selves.(In reply to Fabrice Desré [:fabrice] from comment #60)
> Created attachment 744880 [details] [diff] [review]
> patch
> 
> This patch honors a "app_origin" property in manifests (the one in the zip),
> for signed privileged apps. If you are not running an official build, you
> can test that with non-privileged apps also.
> 
> Note that the origin must be app://foobar, not http(s)://foobar. We don't
> solve any use case that needs systemXHR here, and if we want to address that
> we should do that in a followup.

This makes me very happy. :)

One minor nit: calling the field "app_origin" seems a bit redundant since it's in the app's manifest. Is there a reason not to simply call it "origin"?
The id on ids.json hasn't landed on 1.1 yet for some reason (maybe I'm missing some flag on that bug) and I don't think it was going to land on 1.01 at all. Other than that, and besides the objections of Brian, I have a doubt regarding the patch. When is MOZILLA_OFFICIAL defined? And why make a special case of the origin attribute? I don't think we allow remote installation of non signed privileged apps on any kind of build, do we? Why make an exception here?
(In reply to Brian Smith (:bsmith) from comment #61)
> (In reply to Fabrice Desré [:fabrice] from comment #60)
> > Note that the origin must be app://foobar, not http(s)://foobar. We don't
> > solve any use case that needs systemXHR here, and if we want to address that
> > we should do that in a followup.
> 
> It is important to note that there seems to be a requirement for global
> uniqueness of the app origin. For example, if Developer A develops an app
> with origin app://foobar, then we must ensure that Developer B never
> develops an app with origin app://foobar, regardless of what marketplace it
> is (even ones we don't control) and regardless of how much time has passed
> (if any) between Developer A and Developer B developing their apps.

The current patch enforce unique origins on device.

> Further, we must ensure that the explicit app_origin using in the form of
> the unique IDs that we would auto-generate if it were missing, for the same
> reasons.

If you mean that we must also prevent collisions with our app://$uuid origins, yes we do. If something else, please elaborate.

> IMO, if the only requirement for B2G v1 is that the origin must be stable
> across different installations of the same app, then we could just use
> something like app://marketplace.firefox.com/{ID}, where {ID} is the unique
> identifier that we generated in ids.json for the app.

That would rather be app://{ID}.marketplace.firefox.com . How will the developer know which origin we give to its app though?
(In reply to Matt Basta [:basta] from comment #62)
> > something like app://marketplace.firefox.com/{ID}, where {ID} is the unique
> > identifier that we generated in ids.json for the app.
> 
> Origins don't include paths, and if we're coming up with crazy new "origins"
> that don't follow existing conventions and blaze their own trails then we're
> only making the problem worse.

I agree.

> Additionally, we should not be making the platform dependant on the
> Marketplace. A long-term goal is to support 3rd party marketplaces, and
> adding more and more dependencies on our own marketplace only increases the
> burden on our future selves.

I agree with this too.

However, my point is that it is important to recognize and enforce the uniqueness properties of origins, since permissions and data storage are keyed on origin.

Once you have multiple app stores, you can't rely on them all being able to enforce this important global uniqueness property.

> One minor nit: calling the field "app_origin" seems a bit redundant since
> it's in the app's manifest. Is there a reason not to simply call it "origin"?

I agree with this too.

(In reply to Antonio Manuel Amaya Calvo from comment #63)
> The id on ids.json hasn't landed on 1.1 yet for some reason (maybe I'm
> missing some flag on that bug) and I don't think it was going to land on
> 1.01 at all.

The *enforcement* of the globally-unique IDs and monotonically-increasing versions in Gecko hasn't landed on those branches yet. However, the Firefox Marketplace does include that information in every packaged app already.

> Other than that, and besides the objections of Brian, I have a
> doubt regarding the patch.

Just to be clear: I don't object to the idea of the patch and I didn't look at the specifics. The purpose of my comment is just to remind people that the marketplaces will have to ensure (AFAICT) the uniqueness of this property. That is something that I think is both difficult and error-prone for a single marketplace, and basically impossible for an ecosystem of multiple marketplaces (without incorporating the marketplace's origin into the app origin). But, I wasn't trying to say it is a bad idea.
(In reply to Fabrice Desré [:fabrice] from comment #64)
> The current patch enforce unique origins on device.

Reading the comments above, especially Ben Adida's comments, it seems like the need is for *globally-unique* identifiers, not just *locally-unique* identifiers. Make sure people are happy with the idea that an app might have an app origin of app://facebook.com even though it doesn't have anything to do with facebook.com, and think about what problems it would cause if Facebook tried to use app://facebook.com in a real Facebook app after that other app had already used app://facebook.com. 

> If you mean that we must also prevent collisions with our app://$uuid
> origins, yes we do. If something else, please elaborate.

No, that's what I meant.

> That would rather be app://{ID}.marketplace.firefox.com . How will the
> developer know which origin we give to its app though?

The developer wouldn't know until the app is assigned a version number as part of the publishing process. Presumably the marketplace could provide a way to reserve an (auto-generated) ID prior to publication, and then the author could take that use that reserved ID for testing.

An alternative would be to require the marketplace to verify that, when an app manifest has "origin: app://example.org", that the app author is the owner of the example.org domain name (e.g. by using some kind of email verification scheme to {admin|root|webmaster|etc.@example.org} like DV certificate authorities use).
Can we agree that we need to rely on the signing parties to ensure the origin uniqueness? And also that the developer must be able to choose it? If we use the version number as a prefix, the app will likely need to be updated to use this origin, eg. when limiting postMessage scope. That doesn't look like a nice workflow.

I'll update the patch to use "origin" instead of "app_origin". I can get rid of the MOZ_OFFICIAL switch also (MOZ_OFFICIAL is only set on builds with the official branding) but I guess we must have a way for 3rd party devs to test their app beforehand, potentially without signing - I may be wrong, but I don't think we have a easy way to let devs do that for now.
Attached patch patch v2 (obsolete) — Splinter Review
Updated patch. Changes from v1 are:
- use "origin" instead of "app_origin"
- the value of the origin field does not need to include the protocol part, since we only allow app:// anyway.
- I removed the MOZ_OFFICIAL trick. We don't need that since sideloaded apps can choose their origin when pushing them to the device, and that should be the usual workflow.
Attachment #744880 - Attachment is obsolete: true
(In reply to Fabrice Desré [:fabrice] from comment #67)
> Can we agree that we need to rely on the signing parties to ensure the
> origin uniqueness? And also that the developer must be able to choose it? If
> we use the version number as a prefix, the app will likely need to be
> updated to use this origin, eg. when limiting postMessage scope. That
> doesn't look like a nice workflow.

I agree with all of these points.
(In reply to Fabrice Desré [:fabrice] from comment #67)
> Can we agree that we need to rely on the signing parties to ensure the
> origin uniqueness?

We can only rely on the signing parties to ensure uniqueness with this scheme if and only if there is at most one signing party.

> And also that the developer must be able to choose it?

I think this should be a policy decision of the signing party, not of Gecko. I expect that marketplaces that sign apps will reject apps with misleading origins. For example, I would expect the Firefox Marketplace to reject apps with origin: "facebook.com" if the app was not submitted from Facebook, Inc. Further, the marketplace should probably be conscious of IDN homograph attacks when comparing origins.

> If we use the version number as a prefix, the app will likely need to be
> updated to use this origin, eg. when limiting postMessage scope. That
> doesn't look like a nice workflow.

We shouldn't include the version number. HTTP(S) origins don't have versions.

An origin is scheme://host:port, where port may be implicitly inferred from the scheme. Further, elsewhere in the product we consider "http" to be the default scheme when none is given (e.g. in the address bar); that is a common practice all over the web. So, I think origin: "app://example.org" is much better than origin: "example.org" because it is much less misleading, even though the "app://" could be inferred automatically.
This is part of the requirement to be able to use persona in B2G and avoid hijacking.
blocking-b2g: leo? → leo+
Okay, thanks for triaging this.

I'll await product's input here on the 1.01 decision.
Long thread that I was away for, so I can just confirm what is being done here?

Basically we are proposing to add an "origin" field being adding to the manifest, so that apps reviewed by a marketplace can have a app://{value of origin field} origin, instead of the locally assigned ID.

In order to get this origin:
- the app must be signed,
- its type must be 'privileged' or 'certified' in the manifest
- it must set an origin value in the manifest

And then the big question that is yet to be answered is how we (the marketplace) actually decides what is a valid origin, and who can claim ownership of a given origin. 

Is that on the right track?
You're correct Paul. One small teak is that the "origin" field with need to be the full origin with the app:// scheme - it just looks weird without the scheme.
Comment on attachment 744967 [details] [diff] [review]
patch v2

Review of attachment 744967 [details] [diff] [review]:
-----------------------------------------------------------------

::: dom/apps/src/Webapps.jsm
@@ +2457,5 @@
>                  }
>  
> +                // Check if the app declares which origin it will use.
> +                if (isSigned &&
> +                    app.appStatus > Ci.nsIPrincipal.APP_STATUS_PRIVILEGED &&

Shouldn't this be >= to allow privileged apps to declare origins as well?
Flags: needinfo?(ffos-product)
Some questions:

* Can I check that nothing weird is going to happen if an app changes its origin value in the manifest between versions (e.g. no origin in v1; origin of "foo" in v2; origin of "bar" in v3; no origin in v4)

* What was the conclusion on conflicts?  (i.e. how is the 'uniqueness' enforced?)

* What is the format of the origin string?   "xxx" ? "app://xxx" ? "app://xxx.com" ?
(In reply to Andrew Williamson [:eviljeff] from comment #76)
> Some questions:
> 
> * Can I check that nothing weird is going to happen if an app changes its
> origin value in the manifest between versions (e.g. no origin in v1; origin
> of "foo" in v2; origin of "bar" in v3; no origin in v4)

Changing origin during updates is a no-go. The gecko side will not honor that anyway.

> * What was the conclusion on conflicts?  (i.e. how is the 'uniqueness'
> enforced?)

The platform enforces local uniqueness. I guess it's up to the marketplace team to decide on rules to apply when reviewing.

> * What is the format of the origin string?   "xxx" ? "app://xxx" ?
> "app://xxx.com" ?

This will be app://xxx where xxx can be yyy.com (any valid origin actually).
For the record, the Marketplace currently rejects any manifest with unrecognized fields. That means that nobody could give us a custom origin until we fully accept them and have infrastructure set up to make sure that they behave properly.
(In reply to Fabrice Desré [:fabrice] from comment #77)
> (In reply to Andrew Williamson [:eviljeff] from comment #76)
> > Some questions:
> > 
> > * Can I check that nothing weird is going to happen if an app changes its
> > origin value in the manifest between versions (e.g. no origin in v1; origin
> > of "foo" in v2; origin of "bar" in v3; no origin in v4)
> 
> Changing origin during updates is a no-go. The gecko side will not honor
> that anyway.

So if the origin changed it would just be ignored?  Including if one was not specified previously?  In effect that would mean any app already approved on Marketplace would not be able to take advantage of this new feature.  (I'm not saying this is bad, just making sure I can explain it correctly to developers)
We don't support changing origins, no. That means that users that already installed the app can't get it to use the origin. I understand that this will probably break it if the app itself doesn't check its own origin.
(In reply to Fabrice Desré [:fabrice] from comment #80)
> We don't support changing origins, no. That means that users that already
> installed the app can't get it to use the origin. I understand that this
> will probably break it if the app itself doesn't check its own origin.

Why would the app checking its origin make a difference?  If not having this 'new' origin can be worked around in some other way, then what is the new origin feature for exactly?  If it can't be worked around then doesn't it follow that we can't allow any existing app to add it as it will break for existing users (who won't understand why their upgrade has broken their favourite app).

Apologies if I've misunderstood something here - it was a long thread I read over a short period.
If the app checks it origin and finds out it's not the one expected, it could display a message to the user explaining that he has to uninstall/reinstall. Once again, that's not great but we have no choices at this point.
(In reply to Fabrice Desré [:fabrice] from comment #77)
> Changing origin during updates is a no-go. The gecko side will not honor
> that anyway.

I assume that we are expecting reviews for updates too so regarding our security model, this should be fine, right? What makes that not possible?
(In reply to Fabrice Desré [:fabrice] from comment #82)
> If the app checks it origin and finds out it's not the one expected, it
> could display a message to the user explaining that he has to
> uninstall/reinstall. Once again, that's not great but we have no choices at
> this point.

Note that until bug 817196 is implemented, we wouldn't be able to test this functionality as part of the review process as we can only install the latest version.
(In reply to Mounir Lamouri (:mounir) from comment #83)
> (In reply to Fabrice Desré [:fabrice] from comment #77)
> > Changing origin during updates is a no-go. The gecko side will not honor
> > that anyway.
> 
> I assume that we are expecting reviews for updates too so regarding our
> security model, this should be fine, right? What makes that not possible?

The timeline and risks doing that for 1.1. But in general, yes, we could let apps change origins.
I don't think we should implement support for changing origins.

Remember that we store a lot of data, including permissions, keyed on origin. This means that if an app changes origin, we either have to migrate all of that data, or the application will loose all of its data, including all its permissions.

Implementing data migration is not worth it. This is a passing problem and I'd rather that we spend our time on long term issues, than issues that will go away relatively soon.
(In reply to Jonas Sicking (:sicking) from comment #86)
> I don't think we should implement support for changing origins.
> 
> Remember that we store a lot of data, including permissions, keyed on
> origin. This means that if an app changes origin, we either have to migrate
> all of that data, or the application will loose all of its data, including
> all its permissions.
> 
> Implementing data migration is not worth it. This is a passing problem and
> I'd rather that we spend our time on long term issues, than issues that will
> go away relatively soon.

Can we at minimum try to find a reasonably painless migration path for those who do not specify an origin presently to move to a specified origin without punishing early adopting user and developers? I agree there's no need to allow origin change once an origin is set.
Note that we don't need apps to have unique origins. Or at least we won't need that in the long term.

All data is keyed on application-id (an internal identifier not exposed anywhere) in addition to origin. So it's totally fine to have two apps with the same origin, we'll still be able to tell them apart.

Though what could be tricky is that we generally identify applications by their manifest-url. Fabrice, is that what we're using for packaged apps as well? I.e. are we using app://.../manifest.json? If so we might have a problem.
(In reply to Potch [:potch] from comment #87)
> Can we at minimum try to find a reasonably painless migration path for those
> who do not specify an origin presently to move to a specified origin without
> punishing early adopting user and developers? I agree there's no need to
> allow origin change once an origin is set.

There's no way to do that without writing a lot of sensitive cookie/appcache/httpcache/permission/localStorage/indexedDB migration code.
(In reply to Jonas Sicking (:sicking) from comment #88)
> Note that we don't need apps to have unique origins. Or at least we won't
> need that in the long term.
> 
> All data is keyed on application-id (an internal identifier not exposed
> anywhere) in addition to origin. So it's totally fine to have two apps with
> the same origin, we'll still be able to tell them apart.
> 
> Though what could be tricky is that we generally identify applications by
> their manifest-url. Fabrice, is that what we're using for packaged apps as
> well? I.e. are we using app://.../manifest.json? If so we might have a
> problem.

The only apps that have a app://.../manifest.webapp manifest url are the preloaded ones. All others have http(s):// manifest urls.

The issue with having several packaged apps sharing the same origin is that if app1 and app2 have the same app://greatapp.com origin, we have no good way to know which one is serving app://greatapp.com/icons/logo.png for instance. In a given app context, we could disambiguate using the appId, but not in situations where we allow another app to access cross-packages resources (eg the homescreen).
(In reply to Jonas Sicking (:sicking) from comment #88)
> Note that we don't need apps to have unique origins. Or at least we won't
> need that in the long term.

Even if we don't *need* apps to have unique origin, which I'm not so sure, I don't think allowing different apps to share an origin is a good idea. That would mean that the resource identified by app://whatever.com/index.html depends on the app that's currently running. Even if we can make that work, that's counterintuitive to say the least. And from a security point of view, it's even opposed to what we wanted to achieve in this bug: having a way to identify consistently a window belonging to a given app so we can do things like post messages to that window restricting by its origin. If we allow different apps to share an origin, though, we won't know which app is loaded on that window anymore.

Why would we need this (assigning the same app: URI 'host' to two different apps), anyway?
(In reply to Jonas Sicking (:sicking) from comment #86)
> Remember that we store a lot of data, including permissions, keyed on
> origin. This means that if an app changes origin, we either have to migrate
> all of that data, or the application will loose all of its data, including
> all its permissions.

Do we have to use |manifest.origin| for that? Can't we use the UUID we give to the app instead and simply allow same-origin policy to work with the origin listed in |manifest.origin|?
Blocks: 868967
Frederik, can you CC me to bug 868967 ?
is it a problem that the UUID effectively uniquely identifies a user to the application developer? It would be good that when a user clears private data the UUID used as the origin also changes.
Attached patch part 1: implementation (obsolete) — Splinter Review
This patch let privileged and signed apps specify their origin using the full app://my-origin.is.that syntax.

I'm working on adding an install test, but for now we can only test installs of non-privileged apps :(
Attachment #744967 - Attachment is obsolete: true
Attachment #752283 - Flags: review?(ferjmoreno)
Comment on attachment 752283 [details] [diff] [review]
part 1: implementation

Review of attachment 752283 [details] [diff] [review]:
-----------------------------------------------------------------

Thanks Fabrice! The patch looks good, but I'd like to see the update thing addressed or answered.

::: dom/apps/src/Webapps.jsm
@@ +2557,5 @@
>                    app.appStatus = AppsUtils.getAppManifestStatus(manifest);
>                  }
>  
> +                // Check if the app declares which origin it will use.
> +                if (!aIsUpdate && isSigned &&

Just to confirm. We are not allowing installed apps that don't specify an origin to add an origin during an update.

Can we throw the update in that case instead of allowing it and silently fail to add the origin? The app update might be highly dependent of the origin addition, so IMHO it might be safer to just throw the update and notify about it. The UI could even take advantage of this and notify the user about the need of reinstalling the app to get the latest version.

@@ +2573,5 @@
> +                  }
> +
> +                  debug("Setting origin to " + uri.prePath +
> +                        " for " + app.manifestURL);
> +                  let newId = uri.prePath.substring(6);

let newId = uri.prePath.substring((uri.scheme + "://").length);

or even

let newId = uri.prePath.substring("app://".length);

@@ +2608,5 @@
>                  // Something bad happened when reading the package.
>                  // Unrecoverable error, don't bug the user.
>                  // Apps with installState 'pending' does not produce any
>                  // notification, so we are safe with its current
>                  // downladAvailable state.

typo: downloadAvailable
Attachment #752283 - Flags: review?(ferjmoreno)
Btw, could we also add a test with this patch?
(In reply to Fernando Jiménez Moreno [:ferjm] (needinfo instead of CC, please) from comment #96)
> @@ +2573,5 @@
> > +                  }
> > +
> > +                  debug("Setting origin to " + uri.prePath +
> > +                        " for " + app.manifestURL);
> > +                  let newId = uri.prePath.substring(6);
> 
> let newId = uri.prePath.substring((uri.scheme + "://").length);
> 
> or even
> 
> let newId = uri.prePath.substring("app://".length);

Actually, ignore me about this.
(In reply to Fernando Jiménez Moreno [:ferjm] (needinfo instead of CC, please) from comment #96)
> Comment on attachment 752283 [details] [diff] [review]
> part 1: implementation
> 
> Review of attachment 752283 [details] [diff] [review]:
> -----------------------------------------------------------------
> 
> Thanks Fabrice! The patch looks good, but I'd like to see the update thing
> addressed or answered.
> 
> ::: dom/apps/src/Webapps.jsm
> @@ +2557,5 @@
> >                    app.appStatus = AppsUtils.getAppManifestStatus(manifest);
> >                  }
> >  
> > +                // Check if the app declares which origin it will use.
> > +                if (!aIsUpdate && isSigned &&
> 
> Just to confirm. We are not allowing installed apps that don't specify an
> origin to add an origin during an update.

That's correct.

> Can we throw the update in that case instead of allowing it and silently
> fail to add the origin? The app update might be highly dependent of the
> origin addition, so IMHO it might be safer to just throw the update and
> notify about it. The UI could even take advantage of this and notify the
> user about the need of reinstalling the app to get the latest version.

Sure, we can reject the update.
Now throwing when trying to set an origin during an update, if the origin is different than the current origin.
Attachment #752283 - Attachment is obsolete: true
Attachment #753560 - Flags: review?(ferjmoreno)
Attachment #753560 - Flags: review?(ferjmoreno) → review+
I filed bug 877747 for the test part since David volunteered to write them.
https://hg.mozilla.org/mozilla-central/rev/5330a588cb14
Status: NEW → RESOLVED
Closed: 11 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla24
Keywords: verifyme
QA Contact: jsmith
Blocks: 878094
Flags: in-moztrap?
Blocks: 883185
Depends on: 892764
Most of my testing is finished here except testing a valid app update path. bug 892764 is filed as a followup here, although it's a non-critical bug.
Marking as verified with outstanding issue finishing testing in bug 895708. When bug 895708 is resolved, I'll finish the testing here by caveat.
Whiteboard: [LeoVB+]
Blocks: 929233
Flags: in-moztrap?
I can't sec-review+ this, but I reviewed this a long time ago.
Flags: sec-review?(ptheriault)
Product: Core → Core Graveyard
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: