False Sense of Security

This week a Script Debugger user posted to a mailing list about an unusual AppleScript problem he had just run into.

Steve Mills was writing a script to parse information from a Web page, and the line causing the problem was like this:

set {s, err} to current application's NSString's stringWithContentsOfURL:mainUrl encoding:(current application's NSUTF8StringEncoding) |error|:(reference)

If you are at all familiar with Cocoa or AppleScriptObjC, you will probably recognize that it is trying to download the contents of a Web page, and that mainURL contains the URL to download. Steve’s problem was that it worked fine in Script Debugger, but when he saved it as an applet, he would get an error: The file “xyz.html” couldn't be opened.

We decided to duplicate the test with a test script like this:

use AppleScript version "2.5"
use framework "Foundation"
use scripting additions

set mainUrl to current application's |NSURL|'s URLWithString:"http://apple.com"
set {s, err} to current application's NSString's stringWithContentsOfURL:mainUrl encoding:(current application's NSUTF8StringEncoding) |error|:(reference)
if s is missing value then set s to err's localizedDescription()
display dialog (s as text)

And it worked fine. But when the URL was changed to another page, the result was the same behavior as as Steve.

App Transport Security was already the prime suspect, blocking insecure Web access. Script Debugger has NSAppTransportSecurity/NSAllowsArbitraryLoads enabled in its Info.plist file, which disables App Transport Security, and making a similar change to the test applet’s Info.plist file got it working. Problem solved, sort of — or so it seemed. Steve was going to log a bug, and point out how unhelpful the error message was.

The next day things got more complicated when Steve posted some more information: he had just tried the same exercise from Script Editor, and this time the applet worked fine. Was Script Editor really enabling NSAllowsArbitraryLoads in its applets? We repeated Steve’s tests and looked at the Info.plist files. Not only was Script Editor not enabling NSAllowsArbitraryLoads in the saved applet, but neither was Script Editor itself. To make things even more confusing, when a working applet created in Script Editor and then edited and saved in Script Debugger still worked.

It was puzzling, but I was called away for a couple of hours. By the time I returned, Steve had found the key. When you save an applet, you can specify a unique Bundle ID, usually based upon the reverse DNS name of a domain you own. If you don’t, both Script Editor and Script Debugger generate one for you. Such auto-generated Bundle IDs are based on the name plus the editor’s own ID — so in the case of Script Editor, something like com.apple.ScriptEditor.id.Name-of-App.

And it turns out that having a Bundle ID beginning with com.apple seems to be giving applets a free pass through App Transport Security. Oooh…

Now that we understand the issue, we can look at how it might be addressed in a future version of Script Debugger.

Meanwhile if you face the same issue, the solution is definitely not to use com.apple in your identifiers. Rather, you should edit the application’s Info.plist file, adding a dictionary with the key NSAppTransportSecurity. In turn, this should contain either an entry with the key NSAllowsArbitraryLoads and a value of YES, or one of the finer-grained or domain-specific App Transport Security options.

The Info.plist file lives inside the app bundle in /Contents, and is best edited in Xcode, or carefully in a text editor like BBEdit.

For more details on App Transport Security settings, go here: https://developer.apple.com/library/prerelease/content/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW33

One thought on “False Sense of Security”

Comments are closed.