Starting in macOS 10.12, you can no longer provide external code or data alongside your code-signed app in a zip archive or unsigned disk image. An app distributed outside the Mac App Store runs from a randomized path when it is launched and so cannot access such external resources. To provide secure execution, code sign your disk image itself using the codesign tool, or distribute your app through the Mac App Store. For more information, see the updated revision to macOS Code Signing In Depth.This is further explained in the equally misnamed “OS X Code Signing In Depth“:
If using a disk image to ship an app, users should drag the app from the image to its desired installation location (usually /Applications) before launching it. This also applies to apps installed via ZIP or other archive formats or apps downloaded to the Downloads directory: ask the user to drag the app to /Applications and launch it from there. This practice avoids an attack where a validly signed app launched from a disk image, ZIP archive, or ISO (CD/DVD) image can load malicious code or content from untrusted locations on the same image or archive. Starting with macOS Sierra, running a newly-downloaded app from a disk image, archive, or the Downloads directory will cause Gatekeeper to isolate that app at a unspecified read-only location in the filesystem. This will prevent the app from accessing code or content using relative paths.The gist is, if an app isn’t signed via the Mac App Store, Gatekeeper is going to limit the ability of the app to launch via “Gatekeeper Path Randomization.” Basically, treat an app from a mounted drive as if it were coming from a Safari download. There are a few ways to distribute app bundles or binaries that do not violate this. One is to sign a disk image that contains such an app:
spctl -a -t open --context context:primary-signature -v /Volumes/MyApp/MyApp.dmgIf spctl runs properly, you should see the following:
/Volumes/MyApp/MyAppImage.dmg: accepted source=mydeveloperidIn the above spctl command, we use the following options:
xattr -r -d com.apple.quarantine /Volumes/MyApp/MyAppImage.appThe options in the above use of the xattr command:
xattrdump on a given file, use the -l option as follows:
xattr -l com.apple.quarantine MyAppImage.dmgThe output is as follows:
xattr: No such file: com.apple.quarantine MyAppImage.dmg: com.apple.metadata:kMDItemDownloadedDate: 00000000 62 70 6C 69 73 74 30 30 A1 01 33 41 BE 31 0B A5 |bplist00..3A.1..| 00000010 70 D4 56 08 0A 00 00 00 00 00 00 01 01 00 00 00 |p.V………….| 00000020 00 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 |…………….| 00000030 00 00 00 00 13 |…..| 00000035 MyAppImage.dmg: com.apple.metadata:kMDItemWhereFroms: 00000000 62 70 6C 69 73 74 30 30 A1 01 5F 10 22 63 69 64 |bplist00.._.”cid| 00000010 3A 69 6D 61 67 65 30 30 31 2E 70 6E 67 40 30 31 |:myappimage.dmg@01| 00000020 44 32 36 46 46 44 2E 35 37 31 30 37 30 46 30 08 |D26FFD.571070F0.| 00000030 0A 00 00 00 00 00 00 01 01 00 00 00 00 00 00 00 |…………….| 00000040 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |…………….| 00000050 2F |/| 00000051This could be helpful when troubleshooting and/or scripting (or just way too much informations!). Finally, if you’re an application developer, check out new API for App Translocation in the 10.12 SDK for
<Security/SecTranslocate.h>I guess one way to think of this is… Apple doesn’t want you running software this way any more. And traditionally they lock things down further, not less, so probably best to find alternatives to running apps out of images, from a strategy standpoint.
krypted January 25th, 2017
mdls /Applications/iMovie.appThis results in output similar to the following (I’ve stripped out a few fields as they consume a lot of space and aren’t super pertinent to what I’m trying to do here):
To just ask for one of these attributes, run the command along with the -name option in addition to the metadata attribute you’d like returned. For example, to see the bundle ID (kMDItemCFBundleIdentifier), use:
kMDItemAlternateNames = ( "iMovie.app" ) kMDItemAppStoreCategory = "Video" kMDItemAppStoreCategoryType = "public.app-category.video" kMDItemCFBundleIdentifier = "com.apple.iMovieApp" kMDItemContentCreationDate = 2011-09-28 08:04:34 +0000 kMDItemContentModificationDate = 2012-09-22 02:13:45 +0000 kMDItemContentType = "com.apple.application-bundle" kMDItemDisplayName = "iMovie" kMDItemExecutableArchitectures = ( i386 ) kMDItemFSContentChangeDate = 2012-09-22 02:13:45 +0000 kMDItemFSCreationDate = 2011-09-28 08:04:34 +0000 kMDItemVersion = "9.0.8"
mdls /Applications/iMovie.app -name kMDItemCFBundleIdentifier /Applications/iMovie.appNow, if you’d like to just quickly ascertain what apps on the system came from the App Store, use the mdfind command, along with whatever of the attributes matches what you want to know. Running mdfind for kMDItemAppStoreHasReceipt of 1 would look like the following and would result in a list of all apps on the system that came from the App Store:
mdfind kMDItemAppStoreHasReceipt=1Blacklisting all apps that are part of a specific category (and with regard to customer requests, that category seems to always be Games) is something we get a lot of banter about with customers. To determine this information for apps, you can run mdfind on kMDItemAppStoreCategory for Games:
mdfind kMDItemAppStoreCategory=GamesYou could then dump the contents of those into something that can blacklist apps (or whitelist based on other categories). Now, version control is another hot topic at various organizations. To see the version type of a given app, use the -name option with mdls kMDItemVersion
mdls /Applications/iMovie.app -name kMDItemVersion /Applications/iMovie.appThen you can track the version of the app and take action through other ways to remove old versions and force users to upgrade. The mdfind command can also be leveraged to find apps that have escaped their traditional homes of /Applications and /Applications/Utilities, with the ability to obtain a full list by querying for kMDItemContentType of app bundles, as follows:
mdfind kMDItemContentType="com.apple.application-bundle"Loading a list of apps (output from `mdfind kMDItemAppStoreHasReceipt=1` or `mdfind kMDItemAppStoreCategory=Games`) into an array and then querying each one of them for more information is pretty trivial beyond the steps we’ve already taken. This information can then be fed into some kind of Managed Prefs script to deny or allow access to various objects or an admin could even chmod the bundle, mark it as invisible, poison it (keep in mind, if you alter it you’ll break the signing), etc in order to get some desired outcome. You can also use defaults to read a users com.apple.storeagent.plist file for the AppleID field to see what AppleID is currently logged into the AppStore, providing another variable that can be reported on:
defaults read /Users/cedge/Library/Preferences/com.apple.storeagent.plist AppleIDAnd yes, it’s worth noting that users from another account or a system image, etc can be used to download apps so this one isn’t exactly certain but the purchaser isn’t stored anywhere within the bundle nor is it permissioned in a way that we can use to find the purchaser that way. There’s still a bit of a gap right now with regards to some of these technologies that Mac SysAdmins are managing. The consumeristic technologies such as App Stores are here to stay. We’re kidding ourselves if we think that we won’t be able to buy certain apps via Volume Licenses and have pkg installers for too much longer. Apple has made no indication that they’re dropping the results that can be obtained with a simple installer command, but with forcing signing on certain objects, gatekeeper and other technologies it’s hard to say what the future will really have in store for us. Getting to a point where we can report on elements of the App Store and hopefully eventually deploy objects through the App Store should continue to help bridge these factors, but I still see the need for additional binaries from Apple to be introduced to get the rest of the way there (or at least expose a method to me so I can go in there and buy an app through the method).
krypted November 19th, 2012