Eyes Above The Waves

Robert O'Callahan. Christian. Repatriate Kiwi. Hacker.

Thursday 30 June 2011

Permissions For Web Applications

Summary The permissions model we have evolved for Web applications so far is mostly on the right track; introducing Android-like bundling of permissions with "up front" permission grants would be a mistake.

Traditionally Web applications are untrusted, treated as potentially malicious, and hence "sandboxed" to deny them the ability to affect the user's system or access user data. As we add capabilities to the Web platform, we sometimes encounter situations where legitimate applications want functionality that must be denied to malicious applications. A natural solution is to ask the user whether such requests should be permitted. Long ago we learned that modal requests --- interrupting the application with a warning, and forcing the user to OK/Cancel before proceeding any further --- was ineffective for security, because users quickly learn to OK such warnings without even reading them. An alternative approach is "passive confirmation UI": for example, UI appears requesting a permission, but the user can ignore it and continue using the application, so users who don't read the message are less likely to grant permission by default. Firefox's geolocation permission UI is a good example of this.

The Permissions Bundle Model

That approach seems OK but as apps use more features that require permissions, there is a desire to not bombard users with lots of permission prompts, even passive ones. A number of people have proposed moving to an Android-like model. On stock Android systems, when the user starts using an application for the first time, they are presented with a list of permission requests; the user either grants them all or not. If permissions are denied, the app does not run, otherwise it runs with no further prompts.

Personally I think that is a terrible model. There are two main problems:

  • There is no way for a user to know why an app needs the permissions. For example, Google Music requests, among others, "read phone state and identity", "display system-level alerts", "modify global system settings", and "send sticky broadcast" (whatever that is!). Why should it need to do those things just to play music? I have no idea. Remember that I haven't even been able to run the application yet. As a user, I just don't have the information I need to know whether the request is reasonable or not.
  • If I don't grant the permissions, I can't use the app. Of course I want to use the app, since I downloaded it, so of course I am going to grant the permissions. It's the old OK/Cancel modal dialog all over again.

Someone should do a study where they promote a simple game app which requests absurdly overbroad permissions, and see how many users download the game but reject it at the permissions screen. I'll be amazed if it's more than tiny fraction of users. If so, the permissions screen should be removed, because it provides no security and interferes with usability.


The most important thing we can do is to remove the need to ask for permission to use a feature in the first place. We can often do this by carefully designing our APIs.

Implicit Permission Grants

Good old <input type="file"> accidentally invented an excellent permissions model for file I/O. The app asks the user to choose a file to load, and in the process the user implicitly grants the app permission to read that file! The same sort of approach works in other situations. For example, recently someone proposed that browsers offer permission UI to give an app access to the user's telephone number. Instead, <input type="tel"> could pop up a on-screen keyboard optimized for phone number entry, with access to the user's contacts database and perhaps a "my number" button. Then the application UI would contain "Enter your phone number: []" and the user would easily be able to do so --- or enter another number if they don't want to reveal their own.

Another example of this would be registering Web apps as content-type handlers. Instead of asking for permission to do that, we should simply let any Web app register as any content-type handler. However, when the user downloads content that could be handled by a Web app, then we would prompt the user to choose which app to use, highlighting their last-chosen application and secondarily any newly registered app. (Android does something like this.)

Ask Forgiveness, Not Permission

In many cases the actions of a malicious application can be easily detected and safely undone. For example, the ability to play sound through nearby Bluetooth devices could be abused to annoy the user, but the user will easily be able to detect the problem and the system should offer convenient UI to identify the abusive app and silence it --- per-application volume control. There is no need for a priori permission requests in such cases.

Remember This Decision

I'll assume without further discussion that the system can automatically grant permission to do whatever the app was permitted to do before, unless the user chooses otherwise.

Permissions In Context

Once we've reduced permission requests to the bare minimum, we still have the question of whether to ask for permissions "up front" or while the application is running. I firmly believe it's best for applications to request permission in the context of the user action that requires that permission. For example, it's easy for me to understand that when I click on the "show my location" button in Google Maps, it's going to want my location.

This leaves us with a (smaller) version of the "bombarded by prompts" problem that we started with. Personally I think we should live with it. IMHO the alternative of "bundled permissions" doesn't solve the problem, it simply works around it by teaching users to grant all permissions. "Bombarded by prompts", viewed in a better light, is a process of making informed permission decisions one by one as the user becomes familiar with the app.

Greedy Applications

One wrinkle is that lazy app developers can turn the "permissions in context" model back into the "bundled permissions" model by activating APIs up-front and refusing to let the application proceed until all requests are granted. My hope is that if most apps don't behave that way, users will develop higher expectations and be distrustful of lazy apps.


Points of information: The permission requests happens before download (either the initial download or an update download) and if you look at the comments for an individual app you'll see people talking about the permissions requested -- Angry Birds received a truckload of one-star ratings and was pilloried in the comments a few months ago when they screwed up an update's manifest and it asked for everything under the sun.
Paul Biggar
I love this. I hate not knowing why an app wants permission for something, and I hate having to give blanket permission in advance.
Another problem that is solved by your scheme is the "all or nothing" problem. I don't mind giving out some benign piece of information (like my location) if it doesn't combine it with other information (like the email addresses of everyone I know). So if an app asks for both, I want to be able to deny one and allow the other. Android-style doesn't allow that (it could and should be changed, but that's probably hard to do now).
Paul Biggar
I don't want the "remember this decision" model to be applied in all contexts. It's fine for location, or "access my music", but not for file I/O. If you have permission to read one file, you do not have permission to scan my hard drive.
Colin Walters
Makes sense, and I agree, the Android model is basically worthless. Even if you're one of the 0.1% of users who look at the list, you have to know applications can pass messages to one another, so the permission set is in reality the union of all of the ones from any apps installed from a developer (or cooperating developers).
The Firefox permission bar at the top is kind of lame though, let's admit it =)
In your proposal then, Google Maps would open up to say a view of the world, and have a "Find me" button? Basically for all things that are naturally background, the web platform should encourage app developers to make them foreground?
Robert O'Callahan
Jason: OK, that's interesting. I'd still like to know how many people didn't install Angry Birds because of that.
Paul: CyanogenMod (Android derivative) actually does allow piecemeal permission grants, which is why I carefully said "stock Android". But if your APIs and apps don't expect this from the start, I'd be surprised if it really works.
I don't think we should ever grant an app permission to scan your hard drive. Right now the model has is fine, and it doesn't remember permissions at all. A better example for you would be permission to get input from the microphone; you don't want a site you sometimes use for teleconferencing to always be able to listen to you. So yes, I agree "remember this decision" is not always the right thing (although it often is).
Robert O'Callahan
Colin: what you describe is pretty much how Google Maps works right now.
Ambient stuff like ad targeting which you wouldn't normally trigger on a user action is tricky. I think I'd want the application to offer some kind of UI to enable targeted ads, which would trigger a prompt. If the application wants to restrict its functionality until I've enabled geolocation so it can target its ads, that's its decision, but at least this approach makes it obvious to me as a user what's going on.
So yes, some things that are "naturally backgrounnd" need to come to the foreground, but I think that's OK; if they need the user's permission, then they need the user's attention.
"Ask Forgiveness, Not Permission"
And when I let random strangers into my house, and one of them pisses on the carpet, it's ok because I can throw them out.
Doug Turner
I have been discussing a way to group permissions requests up front. This would allow the user to selectively enable or disable which permissions fit them.
For example, if a webapp wants to use geolocation and to use camera, the webapp could ask the browser for those two permissions (similar to what android does now). However, the user can say "yes, sure", "No", or can select exactly which permissions they feel comfortable with.
If the user selects nothing - or some combination of permissions, the webapp should fall back to doing what it can without those permissions.
Robert O'Callahan
Selectivity is good. However, asking for the permissions up front is still going to have the problems I described.
Robert O'Callahan
One way around having permissions for camera or geolocation would be to have browser or system UI for turning the sensor on. When you turn it on, you would select which application you wanted to use the sensor, with the opportunity to remember that decision and use it automatically until another app that can use the sensor is installed.
So then instead of launching the camera app, you'd turn the rear camera on and either get a choice of apps, or the camera app would just launch. When you turn the front camera on, you'd get a choice or the video call app would launch.
Another possibility is to solve the problem at app discovery time. If the user searches for apps that use the camera, and then installs one, we can take that as an implicit permission grant to use the camera.
Robert O'Callahan
I think for a camera app, the ideal thing would be to grant implicit camera permission because the user installed it from a search for apps that use the camera, but not ask for geolocation up front. The app runs, and you can take pictures and so on. The app should have a preference for whether you tag the photos with geolocation; when you set that preference, you get the geolocation permission prompt.
John Drinkwater
I have an issue with this comment ‘ accidentally invented an excellent permissions model for file I/O’
Load a locally saved HTML page, tell the browser which file to load. It cant load any file outside of the current dir. It cant use it with canvas (to read pixels/load into WebGL). It cant store it in localStorage. It cant post it to any server.
Some of these are Firefox bugs, others are lacking areas of the spec. None of the actions I mention above give user-friendly reasons why they dont work or give the user the ability to grant that action. While it’s awesome to point at the failures in Android, it avoids focusing on the brokenness in engines and spec.
Though, if you insist on looking an Android apps, consider the manifest tag uses-feature, with its required="true"|"false". Surely thats a better model to encourage, requesting permissions and accepting that your user doesnt have to grant it.
I would prefer a javascript application to list wants and have the browser, balanced with my preferences, to inform my consent. Should a widget for statusnet need my password? No.
Should a graphics editor be able to print, post images to flickr, and save to local disk? Yes.
Aryeh Gregor
Android security warnings aren't a bad solution because people ignore them, but because they just don't offer a fair choice. Either you accept some unquantifiable risk that maybe the app will be able to do something bad, or you forfeit the immediate and relatively certain benefit of being able to use the app. A lot of people will rationally and deliberately choose the immediate and certain benefit over the distant and uncertain harm, and it's not fair to call this "ignoring" the prompt. We have to give people the ability to better assess both the cost and benefit of each security decision, which is what the web model helps to do.
The web model isn't ideal, though. It's less convenient for the user, and that's going to discourage authors from using the features. I'd bet there are some sites could use geolocation to slightly enhance their services, but don't because it's not worth bothering the user. I don't know if this will be enough to give a significant advantage to non-web apps over web apps, but it's something to be mindful of. Given the choice, many users will prefer convenience to security or privacy, and the web has to be careful not to err *too* strongly against convenience. I don't have any better suggestions in general, though.
But we can develop smarter UI over time. The decision to install an app is enough to give it access to very high system resource limits, for instance, like disk space, without further prompts. Similarly, it might be fair to allow manually-installed apps to make cross-origin network requests without the user's credentials, say. Or whatever.
I recall reading that BitFrost (the OLPC security model) would allow standard apps to access the filesystem without user interaction only if the app had no network or IPC access whatsoever. That might not be a big use-case for *web* apps, but it's worth mentioning just to highlight the fact that you can have creative solutions here that don't involve pushing decisions off to the user, who can't always make an informed decision.
As for apps that refuse to run unless they're given appropriate permissions, there's an easy solution to that if it becomes a problem: don't tell the author if the user gave permission. For instance, geolocation could always return POSITION_UNAVAILABLE instead of PERMISSION_DENIED. That forces the author to either allow users to deny position or drive away users who can't help it (no GPS, IP geolocation failed).
Hayes Haugen
One useful tool might be to require explicit permission for some things if the site does not have an SSL cert. Doesn't mean the site is not malicious but there is some level of accountability.
Jesse Ruderman
Maybe we should have <input type="location"> in addition to the current geolocation UI. Selecting "use my current location" from an <input> UI could be more natural than clicking a button on the web site and then telling my browser it's okay. Especially if it's something I only use once, such as a store locator.
Alex Faaborg
I agree with most of this (and I'm one of those people who started talking about the benefits of the android model).
I think a summary of my current views, which mostly mesh with your views would be:
-real time prompting for things that impact the user's personal level of privacy (geolocation, camera/video, identity information). This is the part that I don't like about the current android model.
-up front or no prompting for system level access that the user isn't likely to understand anyway (storage, protocol registration, accelerometer, light sensor). This was the part that I liked about the android model.
-we may need to limit some permissions to apps that originate from a reviewed and curated source (bluetooth, NFC, file system access), since these are both very dangerous in terms of security and privacy, and users can't really make informed decisions on them either up from or in real time.
I'm not sure if we agree on that third part though, but I can't see much of an alternative right now.
Robert O'Callahan
Jesse: Yes.
Aryeh: I think we basically agree. I think disk space falls into the "forgiveness, not permission" category; if I'm running out of storage because some app ate it all, I should be able to fix that easily with no harm done.
I do think it's fair to say that when a user keeps being presented with questions they can't answer, they'll make a rational choice to ignore them. How we describe the process that leads to the failure state doesn't matter much :-).
John: Web security depends on origins, and there is no good way to map file:/// URIs to origins, so apps running as "local files" don't work well, that's just how it is. Any model for "installed Web apps" needs to not depend on file URIs.
I believe Jakob Nielsen's Alertbox article on "Workflow Expectations: Presenting Steps at the Right Time" (http://www.useit.com/alertbox/workflow.html) backs up the idea of context based permission requests with user studies (iPad in his tests). He too believes systems like Androids up front requests are confusing for users.
Robert O'Callahan
Thanks for that link! Yes, he seems to agree with my general position, although his data that users decline permission for push notifications defies my expectations that users will say yes to anything. I suspect in this case users see push notifications as particularly obnoxious, and are aware that if they decline the permission, they'll still be able to use the app.
I think you might want to discuss this on mozilla.dev.security.
I've been thinking about how the Android model if completely broken and what could be done instead. A lot of application require way too much permissions, and even the google originated one are guilty of that. Google's Barcode scanner wants to be able to do an uncanny number of things, "because it may be scanning an url and want to open it", "because it may be scanning a contact and want to add it to your list", etc. If it were not coming from Google, I'd never had installed it. Lot of free application want unlimited network access, to be able to download and show advertising, actually it's *less* scaring when you understand what the unlimited network access was for, for an application that no good reason to access the network.
So I've been thinking for a while the solution is something, that's actually the basement for why works. Don't give any right to applications. Give the rights to modules, from which the application can request services, and make sure those modules are very strongly evaluated so that they don't do bad thing.
Here it's a file access module to which the application says "I want an handle of a file" and the file module takes care of the interaction of the user and making sure it the file that the user has willingly provided that the application will have access to and not any file.
Depending on the module, access is provided either automatically or with confirmation. There could be some "Adword", "Yahoo ads" modules, and the applications instead of requesting for network access, would request "Yahoo ads" and you'd know at a much higher and much more useful level what the request really is about.
Aryeh Gregor
Robert: Yeah, the terminology isn't so important, but I prefer to emphasize that the user is making a rational decision when given bad info. Way too many people adopt the attitude of "if only users weren't so stupid!" when users are really being perfectly reasonable. I know you don't feel that way, but I guess I feel it warrants emphasis. I do think we pretty much agree here.
All good points. I want to use the app or web app and have it FAIL when it tries to manipulate my phone/make web requests/access my contacts/read my SD card/track my location/change my Wi-Fi settings/etc. , but let me know when it fails so I can decide if the restricted app meets my needs or whether I should enable. I don't care if some game can't find my location and can't upload my high score to compare with my neighbors and can't tell me that my friends are playing it too.
"we should simply let any Web app register as any content-type handler". Which reminds me, why is it so hard to get content to open in Firefox? I like and trust my browser, I'd love to be able to tell it "Let me view mime-type application/x-vend/Mystery" as text/plain or text/xml in the browser", and only if I like what I see go through the malarkey of saving it and loading some app or plug-in. (I know, I should try the Open in Browser extension.)
@Jason Interesting. I guess when you have a central store with ratings you can have expert users guide the experience of novice users. If an app demands too many privileges, the rating will be lower.
The iPhone (and I suspect other devices too) use the implicit permission grants a lot. By providing standard UI sheets for things like taking a photo, selecting photos from storage, tweeting, emailing etc. Apple can be sure no information will leak out to the app until the user explicitly confirms. So for most apps there's no need to ever present a "This app will use your camera" confirmation, because it will be clear to the user when it's happening, and has a clear exit strategy if they don't want the app to have a photo etc.
Of course, the limitation of this approach is that the app can't enhance the experience.
Robin Berjon
I think that we should distinguish bundled from upfront. Upfront is always bad, irrespective of whether the permissions are bundled or not. It's modal and synchronous: everything you don't want.
Implicit is great when you can have it. People often equate it with creating a new form input type, but that's not necessarily the case (and often carries design issues of its own). Implicit permission can be triggered on valid auto-invocation events for instance, which is what .click() does (and the model followed by http://dev.w3.org/2009/dap/contacts/).
However not everything can be made implicit (or, at least, both implicit and usable) and for those cases bundling — but not upfront — can help make the experience better for the user, and perhaps more importantly avoid the "just click yes" syndrome that's likely to surface if you prompt thrice, even passively. There have been some interesting inputs for bundling, notably a demo playground (http://dev.w3.org/2009/dap/docs/feat-perms/feat-perms.html), a proposed draft spec (http://dev.w3.org/2009/dap/perms/FeaturePermissions.html), and a crack-fueled plan (http://w3c-test.org/dap/proposals/request-feature/). Other thoughts on this: http://berjon.com/blog/2011/02/harmful-trust.html.
Robert O'Callahan
I'm against granting permissions on click(). The assumption that a click conveys trust is false; it's easy to get users to click in a page.
I still don't get why we'd need a bundle API. If the user's input gesture requires more than one permission (a bad situation, and I haven't run into an example where that's necessary), the app can trigger multiple permission requests, and the browser can bundle them automatically in the UI.
Robin Berjon
Your comment system removed some of my input because it contained a markup example instead of just escaping it — that doesn't make communication easy!
When you see "which is what .click() does" I had actually written "which is what {input type=file}.click() does" (except with angle brackets). My point there was that you can trigger {input type=file}-like dialogs on valid self-invocation events even without a matching form control. No one's granting permissions on click — you might as well grant them on load. But it's a decent entry point for implicit permissions.
My concern with bundling is about things that *can't* be adequately obtained through implicit schemes and require passive prompting. Yes indeed you can automatically bundle upon request, but you'd have to speed-bump that prompt to avoid script requesting a new feature just the split second after seeing to mouse leave the viewport to okay the prompt — I'm not sure it would fly through usability testing. DougT also mentioned compile-time analysis of the privileges that will be required. It can be done but there are issues with that as well. At the end of the day I'm all for this being handled automatically, but I have yet to see a design that worked. In security UI, details tend to bite rather nastily :)
John Drinkwater
Robert: Web security depends on origins, and there is no good way to map file:/// URIs to origins, so apps running as "local files" don't work well, that's just how it is. Any model for "installed Web apps" needs to not depend on file URIs.
You’re incorrect in saying they don’t work well - some don’t work at all.
Why should origin treatment for http://example.com/ be any different from eg: file:///home/john/com/example/ ?
Robert O'Callahan
One example to illustrate the problem here:
If I save "http://evil.com/index.html" to /home/roc/evil.html, and I save "http://good.com/index.html" to /home/roc/good.html, and I open those two files in my Web browser, it would be bad to treat them as same-origin, right? But if we don't, then what should the origin be? The full file path? But then, how would I save a page that contains a same-origin IFRAME in a way that's usable?
If you can come up with a bulletproof way to map file paths to origins, I'd love to hear it.
@"If you can come up with a bulletproof way to map file paths to origins" Well, hum, "Mark Of The Web" ??
Peter Gerdes
I think one key feature of a permissions system is to visibly distinguish permissions that might leak information but (whatever they say they want) will almost always allow in practice from permissions that might allow virus/trojans to be loaded or HDs to be wiped. If the permission to let an app use your camera or run an applet with full HD access looks the same as the 'access my location' permission it will get clicked without thinking. More broadly I think what is needed is a way of scoring websites based on their likelihood to distribute malware, collect info, or surreptitiously spy on users. Users could then set sliders indicating how concerned they were about each aspect and only those websites scoring under their concern threshold would require permission. In other words any 'solution' that requires users treat google, facebook and gotomeeting the same way they treat a popup from a sleazy free porn site just won't work. I mean trying to hide your location from google is pretty silly anyway as their network presence and traffic info lets them very precisely pinpoint you using traffic analysis.
David Rogers
Robert, I'm pleased you're thinking about this and it is a hard problem. I spent a long time with others working on BONDI, WAC and DAP and you guys are hitting the same concerns we were before heading for a separate security framework which is firmly in the control of the user or a trusted third party such as an AV vendor. Access to physical features is a very serious step for the web and the security implications are obvious. Having directly written some widgets and played around with different prompting and permissioning, I can tell you that the user can be deluged to the point that it is unusable very very quickly. (Take read phonebook as an example), so I think the value of prompts is limited (but not redundant). As others have said the Android/Chrome model is weak but does have some potentially useful points. I'd be interested in chatting through potential options if you want to speak sometime.
One example to illustrate the problem here: If I save "http://evil.com/index.html" to /home/roc/evil.html, and I save "http://good.com/index.html" to /home/roc/good.html, and I open those two files in my Web browser, it would be bad to treat them as same-origin, right? But if we don't, then what should the origin be? The full file path? But then, how would I save a page that contains a same-origin IFRAME in a way that's usable? If you can come up with a bulletproof way to map file paths to origins, I'd love to hear it.