Wandering Thoughts archives


Why I believe native apps are not doomed by progressive web apps

Recently I was reading Eric Elliot's Native Apps are Doomed (via lobste.rs), which puts forward the premise that most native apps on phones and tablets are going to be replaced by progressive web apps. I disagree with the article, but not for the reasons you might expect. In fact, I think the reason why progressive web apps are not going to replace native apps is summarized quite neatly by another recent web related story, of Firefox removing the Battery Status API. Firefox hasn't taken this step because the API doesn't work or isn't used. It's the other way around; the API works too well. As with a number of other web APIs, clever people are abusing the API to surreptitiously extract privacy-invasive information from people's browsers. This is the problem with a lot of powerful device-related APIs that are accessible to websites; many of them have turned out to be great ways to fingerprint devices or invade privacy in other ways.

In my opinion, this is the core problem of progressive web apps and the core advantage of native apps. Progressive web apps are fundamentally websites, yet to create an experience comparable to native apps they want access to powerful and invasive device APIs that are likely to be increasingly restricted or simply unavailable (as Battery Status is likely to end up). Given this, it's worth asking just why native apps get to have such powerful access (beyond simply 'history'). In my view, this has two parts.

First, native apps generally require active installation and then actively being invoked before they can do any harm; they don't just appear, running (not if the phone's OS has anything to say about it). This gives the phone's user a lot of chances to bail out or to limit the damage an intrusive app might do (even by something as simple as not running it very often because you're not interested in it). Second, native apps are generally at least a bit screened by the app store involved in an attempt (in part) to catch nasty apps. And if something egregious is later discovered in an app, the app store can generally do something about it. This is a deliberate choice on the part of app stores; they want to create user trust because users who trust apps to not be evil are users who are willing to install more of them.

It's pretty clear that you can't give progressive web apps either of these two things without making them basically an implementation technique for native apps, which is not really what people want for them. If you want the freedom of the web, you get the security problems of the web too and with them the limitations that phone browsers are going to impose on the web in order to protect their users.

(Permission popups for websites are not the answer, not if the phone actually cares about protecting people. First, you'd need far too many of them in order to give access to all the device APIs. Second, in practice pervasive popups lead to alert fatigue, causing users to blindly approve everything.)

PS: Given the privacy risks created by new browser-accessible device APIs, the easy approach for phone and tablet vendors is simply to not create them. While you might be able to create an API without privacy risks or with low privacy risks, it's clearly going to take more work and you risk screwing it up. Doing nothing, creating no API, definitely does not create privacy risks and it takes no work either, and you can tell people who want those APIs 'make a native app'.

web/NativeAppsNotDoomed written at 23:24:23; Add Comment

Modern shells and running shell scripts while seteuid

You can't and shouldn't make a shell script setuid, but there are times when you can want to deliberately run a shell script from within a seteuid context, especially a seteuid root one. One case for this is if you want to kick off a script from PAM module that may be run for, eg, password changes.

I will cut to the chase: you probably don't want to do this today, because modern Unixes or more exactly modern shells on Unixes are making this harder and harder to do reliably. If at all possible, transition fully to the new UID you want the shell script to operate under, either by doing the appropriate setuid() call in your own code before you invoke the script or by changing how the entire system is invoked (for example, by doing things through sudo).

In the old days of Unix, shells were blithely unconcerned about security issues; those were your problem, and it was up to you to do things right. Over time, it became obvious that a certain number of people were not going to do things right and that perhaps it would be a good idea for shells to save people from themselves, at least some of the time. For example, one fruitful source of security issues here is setuid programs using popen() to run things. popen() starts a shell, which was running seteuid, and there are any number of ways to subvert a shell if you aren't careful (especially modern shells, which can have their behavior influenced by any number of environment variables).

So shells started saving people from themselves in this situation. If you start a modern shell in a seteuid environment and don't give it a special flag (people seem to have standardized on -p), it immediately drops seteuid privileges and generally also ignores a number of environment variables that would normally influence its behavior.

(Some shells in the Bourne family will do this all of the time, even if they're being used as /bin/sh, but some of them will do this only if they're invoked under their own name and stick to the traditional behavior when run as /bin/sh. The latter is less secure but more compatible with existing behavior.)

This presents not one but two problems if you intend to run a shell script in such a seteuid environment on a modern Unix with such a modern shell. The obvious and direct problem is that you have to make sure to start the shell script with '#!/bin/sh -p' or '#!/bin/bash -p' or the like; otherwise the shell will immediately drop permissions on you. The good news is that you're probably going to notice and fix this right away, at least once you work out what's happening.

The less obvious problem is that running your own script with -p has armed a gun that's pointed at any other shell scripts that your script runs. Unless those scripts also start with -p, they may (or will) immediately drop seteuid when they start to run and will quite possibly malfunction as a result. Effectively, running with -p poisons your environment in a subtle way. It's possible to work around this in various ways, but it makes your whole shell script fragile; all you need is one thing that your script runs deciding to call a shell script that doesn't have a -p and things can blow up.

(And naturally many of the things that your script uses may not ever have thought about this, because they're just regular scripts, not special security-related scripts that ever expected to run in a seteuid environment. Some of them may not even really be safe in a seteuid environment in general, so just slapping a -p on them is dangerous in its own way.)

Given that running seteuid is now a taint as far as modern shells are concerned, it's more reliable to avoid this taint in the first place. In other words, run your initial shell script without it being seteuid (one way or another).

unix/ModernShellsAndSeteuid written at 02:01:25; Add Comment

Page tools: See As Normal.
Login: Password:
Atom Syndication: Recent Pages, Recent Comments.

This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.