Posts in Category "design decisions"

AIR’s Unrestricted System Access Warning

[Update 2009-07-30: This dialog has been revised for AIR 1.5.2.]

If you’ve ever installed an Adobe AIR-based application–you have installed one, right?–then you’ve probably noticed the installation screen warning that the application you’re installing will have unrestricted system access. I’m frequently asked by developers how they can get rid of this warning, lest it scare off some of their customers. The short answer: you can’t.

When we developed the installation screens for AIR, one of our major goals was to make sure they were informative. Installing an application on your machine is a big deal. You’re trusting code that someone else wrote to not steal or destroy your information. If you’re going to do this, you ought to be well-informed regarding what you’re installing and what risk you’re taking.

The “unrestricted system access” warning is there to make sure you know that, once you install this application, you’re trusting it to behave. No one else is going to keep an eye on it for you.

Some future release of AIR might offer to perform this function for you–that is, restrict the system access of certain applications. With that capability, you might make different decisions about which applications to install. But that’s all theoretical for now. Right now, all application are unrestricted. Even if they don’t need to, say, access the filesystem, they still can. So that warning shows up every time.

How do you know, then, which applications to trust? I recommend making that decision based on the publisher’s identity–the other major piece of information on that first installations screen.

The AIR Browser API and User Events

The AIR browser API lets web applications detect, install, and launch AIR applications. There are some restrictions on its use, however:

  • Applications have to opt-in to the detect and launch capability. This is done by specifying <allowsBrowserInvocation> in the application’s descriptor.
  • Installing and launching applications can only be performed in the context of a user event

“In the context of a user event” means that the method is called during an event handler for some event, such as a mouse click, that’s initiated by a user action, such as clicking on a button. Note that this doesn’t mean all mouse events qualify, as they can also be dispatched programmatically.

Why this restriction? To protect the user against malicious (or just really annoying) web pages. WIthout this restriction, pages could install and launch applications as soon as the page is loaded, over and over again, until you give up in disgust and quit using the Internet.

This restriction occasionally trips people up when using the browser API because it’s tempting to wait for a user event, then call getApplicationVersion() to determine whether or not the application is installed, and finally call installApplication() or launchApplication(). But this won’t work because the getApplicationVersion() call is asynchronous; when the specified callback function executes, the code is no longer part of the original user event.

Note that getApplicationVersion(), however, need not be called during a user event. The trick, then, is to call this method right away, when your web page loads. By the time the user clicks on the button, you’ll already know whether you need to install or launch and can do either immediately within the context of the user event.

One final note: consider calling getApplicationVersion() periodically from a Timer. That way, if the application install state does change while the page is open, subsequent clicks on that button will continue to do the right thing.

Version Numbers and the Updater API

AIR applications can update themselves via the Updater API. It’s straightforward to use: you just provide an AIR file containing the new version of your application and the version number you’re upgrading to. Downloading the AIR file and displaying any appropriate UI is left to the application.

When we designed this API, I thought we’d get a lot of questions about why the version number had to be provided. After all, the version was itself embedded in the AIR file. Surely we could just grab the version number from there, right?

Disappointingly, few have asked.

Disappointing because that argument exists to help you protect your application from downgrade attacks. Downgrade attacks work like this: some earlier version of your application has a vulnerability, but has since been patched. The attacker tricks your update mechanism into using the Update API to install that old version, thus re-introducing the vulnerability. Then they attack the vulnerability.

To protect against this attack, the application must validate before it begins the update that the version it’s updating to is, in fact, a newer version. During the update process itself, AIR will validate that the version number you’ve validated and passed to the update call does in fact match the version in the AIR file. If they don’t match exactly, the update will fail.

Why doesn’t AIR check that the version is newer? Because we didn’t want to impose a version numbering scheme on anyone.

Parameterized Application Install

I’ve been asked a couple of times if it’s possible to parameterize the application identifier, etc. for an AIR-based application during the installation process. The scenario is usually something like this: A developer has created an application that they publish through different vendors. Each vendor stamps some unique branding, etc. on the application but the underlying code is the same. The developer doesn’t want to produce a different AIR file for each vendor. Instead, they’d like to parameterize things like the application identifier, application name, logo, etc. during the installation process.

The problem with this is that it’s directly at odds with secure delivery of the applications. Secure delivery is designed to establish the trusted identity of the publisher of each application via digital signatures. If any part of the application can be changed at install time then it’s (by definition) not covered by that signature, and we can no longer establish the authenticity of the application. Maybe you got assigned a correct parameter, or maybe you got a malicious one that will open you to an attack. How do you know?

In these scenarios it’s the vendor, not the developer, who is actually publishing the application. They’re the ones who should be signing the application; this will insure that it’s their name that appears during application install. And of course they should only be signing it after any re-branding, etc. has been applied.

Too much work for the developer? It shouldn’t be. Packaging can be fully automated via the adt tool provided for free in the SDK. Create a script that uses it to produce all of your unsigned, parameterized, intermediate AIR (.airi) files. Hand this file off to your vendor and have them sign it, again using adt, to produce the final AIR file for distribution. Voila.