(Skippable) Backstory:
I have an app that customers initially install by:
Going to our website in a browser,
downloading a (notarized) disk image,
mounting it,
opening the (Developer ID-signed) installer package therein, and
following the prompts to completion.
Once installed, this app has a button you can click that will check for updates and possibly install them. When you click this button:
Our app contacts an HTTPS API on our servers to see if there is an update
If there is an update, the API responds with a download URL to the aforementioned notarized disk image, and the SHA-512 hash of the disk image
Our app downloads the disk image, and verifies the SHA-512 hash of the download
Our app mounts the DMG
Our app uses /usr/sbin/pkgutil --check-signature (although I do hope to switch to SecStaticCodeCheckValidity() in the future) to verify that
the OS thinks that the installer package is properly signed, and also that
the organization unit on the leaf certificate for the code signing key used to sign the installer is exactly equal to our Apple Team ID
Our app uses /usr/sbin/installer -package ... -volinfo to verify that the installer package thinks it can install onto the host
Our app uses /usr/sbin/installer -package ... -target / to install the software update
For 98%+ of our users, this update process works great. For a tiny portion of users, we're seeing that hdiutil reports that it failed to attach the disk image. For the even tinier portion of users from whom we have obtained debug logs, one of the errors we've seen is "not recognized"; however, I don't know if that's the most common error, due to the small sample size.
Before I get much further, I think it's prudent to acknowledge that the above system we're using today is pushing a decade old now, and it's probably wise to verify the foundations.
So...
For a Developer-ID-signed macOS app that is distributed outside the Mac App Store using an installer package, what is the "best" container/packaging system for an automated system to obtain and consume the installer package with the goal of a user-initiated self-update? For example:
Notarized disk image (and failures to attach the image need to be bug reports to Apple)
Just the installer package (If I understand correctly, this is bad because it bypasses the automatic propagation (normally performed by macOS) of the DMG's notary ticket to the pkg, right?)
Something else?
Secondly, what are some common developer mistakes to avoid? For example, these come to mind:
When saving the DMG to disk, explicitly enable quarantine on the DMG, so that macOS runs appropriate security checks as intended (is this correct?)
When running the installer package, do not use low-level tools (like cp) to copy the pkg out of the DMG, because macOS won't be able to automatically find the notary ticket when the pkg is installed (is this correct?)
Anything else?
Additional context:
We currently support macOS 10.13+, but we will soon support only macOS 10.15+.
Thank you!
Gatekeeper
RSS for tagGatekeeper on macOS helps protect users from downloading and installing malicious software by checking for a Developer ID certificate from apps distributed outside the Mac App Store.
Posts under Gatekeeper tag
55 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
I got the python app notarized and downloaded it fine.
However, if you are caught by Gatekeeper and open the information window, you will see a lock and even if you enter the password to open the lock, it will not work.
xattr -d com.apple.quarantine ./test.app
You have to exclude it from the gatekeeper directly.
I wonder if the downloaded app is unavoidable... or if there is another way.
I have an installation workflow that works by a user double clicking on the mpkg and going through the prompts to install some software. Within the postinstall of the mpkg, /usr/sbin/installer -pkg "path_to_pkg" -target / is done to install additional software.
The software contained in the mpkg contains system extensions and installs without issue.
The software contained in the pkg file also contains system extensions and a prompt with this message displayed.
"XSoftware" is damaged and can't be opened. You should move it to the Trash
This file was downloaded on an unknown date.
This is causing issues with the system extension being installed from XSoftware.
Curiously enough, when I run /usr/sbin/installer -pkg "path_to_pkg" -target / manually in a terminal window it works successfully and XSoftware is able to install the System Extensions and run properly.
I've used the pkgutil --check-signature to check the notarization and signing and it looks correct.
This is my dmg structure:
dmg
|
mpkg
data_folder
|
pkg
Any suggestions or help would be greatly appreciated. I can provide more details if neccessary.
Hi, we have an app that has been in development since Catalina and ever since Sonoma came out we noticed that when executing our pkg installer the application is installed correctly but the postinstall script is not executed.
The weird thing is that if I run the pkg for the first time the postinstall does not execute BUT if I run it again then it DOES!!
Looking through the logs I found these ones that confirm the execution of the script is being blocked. We haven't changed anything in the way we build the installer so I'm not quite sure how to fix this.
2024-04-25 16:29:51.570662-0300 0x1c62 Error 0x0 308 0 syspolicyd: [com.apple.syspolicy.exec:default] Unable (errno: 2) to read file at <private> for pid: 784 process path: <private> library path: (null)
2024-04-25 16:29:51.570662-0300 0x1c62 Error 0x0 308 0 syspolicyd: [com.apple.syspolicy.exec:default] Terminating process due to Malware rejection: 784, <private>
2024-04-25 16:29:51.570679-0300 0x1d13 Default 0x0 0 0 kernel: (AppleSystemPolicy) ASP: Sleep interrupted, signal 0x100
2024-04-25 16:29:51.570682-0300 0x1d13 Default 0x0 0 0 kernel: (AppleSystemPolicy) ASP: Security policy would not allow process: 784, /private/tmp/PKInstallSandbox.m5Av3O/Scripts/com.mycompany.myapp.pkg.BSOjtt/postinstall
The app as well as the installer are both signed, notarized and stapled. Here you can see the script which just simply executes the app.
#!/bin/bash
echo "Running postinstall"
/Applications/myapp.app/Contents/MacOS/myapp --load-system-extension &
exit 0
Any help would be much appreciated. Thanks!
Hi everyone,
Has this every happened to you? If so, how did you resolve it?
Submitting my app for review, I got the following rejection:
Guideline 2.4.5(ii) - Performance
The package currently available in App Store Connect cannot be installed and may be corrupted.
Next Steps
Please rebuild your application and upload a new version. If this issue continues, please contact Apple Developer Technical Support for help investigating the issue.
DTS referred me back to app review:
We are unable to help you resolve this matter. Please circle back with the App Review team for assistance.
I'm building the .pkg with productbuild:
xcrun productbuild --product WFH\ Phone\ Webcam.app/Contents/Info.plist --component WFH\ Phone\ Webcam.app /Applications --sign "3rd Party Mac Developer Installer: Mansour Moufid (42A2D88R9U)" --timestamp WFH\ Phone\ Webcam.pkg
and uploading it with altool:
xcrun altool --username "..." --password "..." --validate-app --file WFH\ Phone\ Webcam.pkg --type osx
xcrun altool --username "..." --password "..." --upload-app --file WFH\ Phone\ Webcam.pkg --type osx
The .pkg signature looks fine:
xcrun pkgutil --check-signature WFH\ Phone\ Webcam.pkg
Package "WFH Phone Webcam.pkg":
Status: signed by a developer certificate issued by Apple (Development)
Signed with a trusted timestamp on: 2024-04-29 14:11:27 +0000
Certificate Chain:
1. 3rd Party Mac Developer Installer: Mansour Moufid (42A2D88R9U)
Expires: 2025-03-13 20:11:55 +0000
SHA256 Fingerprint:
CB 8A 12 1D 4D 16 29 27 08 30 07 1C 6C F6 1C F4 85 6E AE F1 B1 34
68 F7 81 6D C3 3B 1B 8C 5D 32
------------------------------------------------------------------------
2. Apple Worldwide Developer Relations Certification Authority
Expires: 2030-02-20 00:00:00 +0000
SHA256 Fingerprint:
DC F2 18 78 C7 7F 41 98 E4 B4 61 4F 03 D6 96 D8 9C 66 C6 60 08 D4
24 4E 1B 99 16 1A AC 91 60 1F
------------------------------------------------------------------------
3. Apple Root CA
Expires: 2035-02-09 21:40:36 +0000
SHA256 Fingerprint:
B0 B1 73 0E CB C7 FF 45 05 14 2C 49 F1 29 5E 6E DA 6B CA ED 7E 2C
68 C5 BE 91 B5 A1 10 01 F0 24
The app's signature also checks out:
codesign --strict --deep --verbose --verify WFH\ Phone\ Webcam.app
WFH Phone Webcam.app: valid on disk
WFH Phone Webcam.app: satisfies its Designated Requirement
I have no idea what "cannot be installed and may be corrupted" means and app review is not responding to my request for more information...
I have two apps written in MAUI Mac Catalyst Framework -- one is main app, second is app updater. My updater works this way: it is located in the same directory as main app: firstly it deletes MainApp.app/Contents folder, then unzips new Contents folder that was downloaded from server.
I added NSUpdateSecurityPolicy dictionary as in https://developer.apple.com/documentation/bundleresources/information_property_list/nsupdatesecuritypolicy and create application like . It looks that I wrote everything fine
pkgbuild --install-location '/Library/Application Support/First' --root root --ownership preserve # aslo signing, etc
But on user's macOS, system does not allow to delete Contents folder: I have IO_Access denied exception. Can it be because main app is sandboxing or something else?
What I can do wrong? Thanks a lot in advance!
I am not enrolled in the Apple developer program and need to create a small Safari app extension helper that will be shared with my colleagues within the company. Is it somehow possible for me to distribute the app in some way without forcing everyone to disable a gatekeeper?
I have two apps that installed by .pkg . They are both signed by Developer Application . One of my apps has purpose of updating another app. It is implemented by deleteting it from folder, and unzipping archive with new .app to it's folder. Even if new app is signed and notarized, has stepled ticket on it, I get error "App is damaged and can't be opened". In Secrity and Confidentiality preferences I have warning that developer is unauthorized, even if this new app is notarized and signed. How can I implement app update to not throw error that app is damaged> Thanks a lot in advance
We have developed an application in which we have a main application and there are several loadable bundles which are loaded from within the main application.
We archive the main application and generate the .app file. When we run the app, everything works fine and it loads the bundles.
But when notarise the main application, it stops loading the bundles. We think we will need to notarise the bundles as well but not able to find the ways to do it.
Any help will be very appreciated.
Could someone let me know if it is possible to create a self-signed Developer ID Installer certificate? Create an installer package using this certificate. And share it with others. This is just to do a simple proof of concept.
I am working on an open source app. I have been testing the package installer, and something unexpected is happening: the .pkg won't run on my test machine and will instead show a banner saying "myApp.app can't be opened because Apple cannot check it for malicious software"; nevertheless, if I wait some minutes, the installer will run just fine!
After reading through many of ekimo's posts, I assumed it may have something to do with stapler. I was not stapling my .dmg originally, so that's something I may be missing (my app is installed by a .pkg inside a .dmg). Nevertheless, the computer where I am testing the app has internet connection, meaning stapler should not even come into play.
Regardless, I decided to staple my .dmg. Running xcrun stapler staple -v myApp.dmg after notarizing produces this result:
builder ~ % xcrun stapler staple -v /Users/builder/Data/HEAD/installation/Packages/myApp.dmg
Processing: /Users/builder/Data/HEAD/installation/Packages/myApp.dmg
Properties are {
NSURLIsDirectoryKey = 0;
NSURLIsPackageKey = 0;
NSURLIsSymbolicLinkKey = 0;
NSURLLocalizedTypeDescriptionKey = "Disk Image";
NSURLTypeIdentifierKey = "com.apple.disk-image-udif";
"_NSURLIsApplicationKey" = 0;
}
Creating synthetic cdHash for unsigned disk image, myApp.dmg. Humanity must endure.
Signing information is {
cdhashes = (
{length = 20, bytes = 0xdd018313b1c574a403f01dccc96c21705987d76c}
);
"cdhashes-full" = {
2 = {length = 32, bytes = 0xdd018313 b1c574a4 03f01dcc c96c2170 ... 918d33f3 d5a74dc3 };
};
cms = {length = 0, bytes = 0x};
"digest-algorithm" = 2;
"digest-algorithms" = (
2
);
flags = 2;
format = "disk image";
identifier = ADHOC;
"main-executable" = "file:///Users/builder/Data/HEAD/installation/Packages/myApp.dmg";
source = "explicit detached";
unique = {length = 20, bytes = 0xdd018313b1c574a403f01dccc96c21705987d76c};
}
Stored Codesign length: 12 number of blobs: 0
Total Length: 12 Found blobs: 0
JSON Data is {
records = (
{
recordName = "2/2/dd018313b1c574a403f01dccc96c21705987d76c";
}
);
}
Headers: {
"Content-Type" = "application/json";
}
Domain is api.apple-cloudkit.com
Response is <NSHTTPURLResponse: 0x600003b85ba0> { URL: https://api.apple-cloudkit.com/database/1/com.apple.gk.ticket-delivery/production/public/records/lookup } { Status Code: 200, Headers {
Connection = (
"keep-alive"
);
"Content-Encoding" = (
gzip
);
"Content-Type" = (
"application/json; charset=UTF-8"
);
Date = (
"Mon, 26 Feb 2024 15:34:15 GMT"
);
Server = (
"AppleHttpServer/78689afb4479"
);
"Strict-Transport-Security" = (
"max-age=31536000; includeSubDomains;"
);
"Transfer-Encoding" = (
Identity
);
Via = (
"xrail:st53p00ic-qujn15041902.me.com:8301:24R11:grp60,631194250daa17e24277dea86cf30319:59e17ac665e1de7388b8f4e69e92e383:defra2"
);
"X-Apple-CloudKit-Version" = (
"1.0"
);
"X-Apple-Edge-Response-Time" = (
99
);
"X-Apple-Request-UUID" = (
"9fc0fe2d-49fd-4e74-b718-660c56edb3bb"
);
"X-Responding-Instance" = (
"ckdatabasews:16306401:st42p63ic-ztfb05112901:8807:2409B432:afc827b7b1ebf24829e9c4856d4b69205f23804f"
);
"access-control-expose-headers" = (
"X-Apple-Request-UUID,X-Responding-Instance,Via"
);
"x-apple-user-partition" = (
63
);
} }
Size of data is 165
JSON Response is: {
records = (
{
reason = "Record not found";
recordName = "2/2/dd018313b1c574a403f01dccc96c21705987d76c";
serverErrorCode = "NOT_FOUND";
}
);
}
CloudKit query for myApp.dmg (2/dd018313b1c574a403f01dccc96c21705987d76c) failed due to "Record not found".
Could not find base64 encoded ticket in response for 2/dd018313b1c574a403f01dccc96c21705987d76c
The staple and validate action failed! Error 65
What does this show?
Thank you.
I've been trying to submit an application made with the Electron framework (electronjs.org) to the Mac Apple Store, but when launched an alert dialog appears with the text:
"App Name Helper (Renderer)" differs from previously opened versions. Are you sure you want to open it? Opening "App Name Helper (Renderer)" will allow it to access data from previously used versions of "App Name Helper (Renderer)".
...this is preventing my Mac App Store submission. I've looked at troubleshooting information related to Gatekeeper and entitlements, etc. but I have not been able to determine which Apple subsystem (App Sandbox? Gatekeeper?) this particular alert comes from so I can possibly carve out an exception for it, or otherwise figure out how to fix it.
"App Name Helper (Renderer)" is an agent process. Checking the App Store build results in:
> spctl -a -t exec -vvv App\ Name.app/Contents/Frameworks/App\ Name\ Helper\ \(Renderer\).app
App Name.app/Contents/Frameworks/App Name Helper (Renderer).app: rejected
origin=Apple Distribution: Kevin Hughes (MYTEAMID)
...for App Store submission, is it expected that all agent processes should be signed with the Apple Distribution certificate? And is it OK that nothing is notarized before submission? If everything should be notarized, which certificate should be used? Does the App Store verification process check for this kind of thing regarding agent processes? Should it?
Note that I can build, install, launch, and fully execute an Apple Developer ID-signed and notarized binary with a hardened runtime (and Apple Development profile) myself on my local machine as well as other macOS Sonoma 14.3.1 systems without any issues. The entitlements for my App Store build are:
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.assets.movies.read-only</key>
<true/>
<key>com.apple.security.assets.music.read-only</key>
<true/>
<key>com.apple.security.assets.pictures.read-only</key>
<true/>
<key>com.apple.security.automation.apple-events</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.debugger</key>
<true/>
<key>com.apple.security.cs.disable-executable-page-protection</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
<key>com.apple.security.files.downloads.read-only</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
Hello,
I'm running into an issue when code signing my .app file on macOS. After introducing the --entitlements flag, I'm encountering an error that prevents the app from launching:
Error Messages:
App UI: "Cannot open the file"
Terminal (using open file.app)
The application cannot be opened for an unexpected reason, error=Error Domain=RBSRequestErrorDomain Code=5 "Launch failed." UserInfo={NSLocalizedFailureReason=Launch failed., NSUnderlyingError=0x60000216d620 {Error Domain=NSPOSIXErrorDomain Code=153 "Unknown error: 153" UserInfo={NSLocalizedDescription=Launchd job spawn failed}}}
Troubleshooting Details:
Without code signing, the app launches and permission pop-ups function correctly (the file tauri generates).
With code signing (but without --entitlements), the app launches but there are no permission pop-ups.
All scenarios (without signing, with signing, with signing + --entitlements) all have Info.plist in the /Contents of the .app file
Notarizing and stapling works fine when I do not include the --entitlements flag when signing.
Code for signing with entitlements:
codesign --timestamp --sign "Developer ID Application: ()" --options=runtime --entitlements ./src-tauri/Info.plist "${APP_FILE}"
Specifications
MacBook Air, M2, 16GB
macOS Sonoma 14.3.1
Xcode 15.2 (Build version 15C500b)
We are using an iPhone app distributed as an AdHoc app, but an error message saying "App cannot be verified" was displayed.
The error screen says, "Internet connection is required to verify the credibility of developer "Apple Distribution:●●●● CO.,LTD.(QQQ29B8GG2)"."
When using this app, We are connected to the LAN, but not connected to the Internet.
If you temporarily connect to the Internet and start the app when the error screen appears, the error screen will disappear.
After that, when I switched from connecting to the Internet to connecting to LAN, it worked normally for a while, but after about 2 months, the same error screen appears again.
Please tell me how to resolve this error.
Hello
I jump on my mac every 3-4 months to release new version of my apps. Process usually is "ok" some cmake/compile issues as 99% of dev is done on windows but other than that its all good.
But now I'm stuck.
My app can run locally/start etc just fine, but clients are panicking because they can't run them. They have undefined developer warning.
I don't understand this. Its notarised and been working for 2 years. What am I doing wrong ?!
How can I test it ? I tried creating new user-profile on my mac, but there is no issue, app starts. Do I need to buy ANOTHER mac to test my apps before release ?!
Can any1 help how to debug this issue? I'm lost,
I used finder-compress myapp.app & send it via slack to client to get him quickly going but that does not help either. - I though it was zip stripping down data or something.
Anyway, very frustrated here, and lost. Can any1 help? hint?
Is this good resource to check against?
https://developer.apple.com/library/archive/documentation/Security/Conceptual/CodeSigningGuide/Procedures/Procedures.html
I've run spctl --assess --type execute myApp and I'm getting rejected (bundle format is ambiguous (could be app or framework))
But then why does it notarize/sign/etc with no errors ?!
I'm so lost :- ((((
Any help would be greatly appreciated
I've attached app content >
Ok I've tested my older releases, they all have the same issue but they all work on client system. I'm so lost :- (((
Hi,
I've ran into an issue which only seems to affect one of my macs.
It's currently running 14.2.1 but I first saw this issue in 13.6.
If I download the macOS Sonoma 14.2.1 installer (via App store) onto this particular machine, it will never execute the installer. It always reports that the installer is "damaged". Of course I did reasearch this online and you get the usual unhelpful posts which just say "re download it" and of course, I wouldn't be posting here had I not tried that.
This happens with any macOS installer I download using the softwareupdate --fetch-full-installer utility as well. The thing is, if I copy this .app to another (identical as far as I can tell) Mac - it will work. So far this also seems limited to macOS installers - other third party apps are fine. I'm convinced this is related to trusted execution and something has gone wrong in the environment. I've been looking at my router logs to see if any connections may have been blocked (I'm using OPNsense) and also looking to see what connections are being made via Little Snitch and so far it looks fine. Again, other machines on the network can run these just fine.
I've read through eskimo's excellent guide here: https://forums.developer.apple.com/forums/thread/706442 but I was wondering if anyone can give me some pointers to narrow this down further.
As it stands, I can't trust this machine for app development if I can't even get the official Apple installers to run sucessfully.
I have an non-appstore application, using developer id which I want to transfer to another developer account.
How can I go about doing this?
How do I transfer the app ID?
Will past versions of that app signed with the old account continue to work? Will I have to re-sign them?
I want to distribute my app with my developer ID.
This works fine in a dmg or zip container if I download it on another Mac by FTP.
But if I download it by HTTPS macOS brings a Popup:
“Rocrail.app” is damaged and can’t be opened. You should move it to the Bin.
I don't understand the diff between FTP and HTTPS download...
How can I fix this?
Hi,
We have an app that installs a number of system extensions. According to this documentation the app must be located in the Applications folder to be activated so when the app launches we check that it is running from /Applications (or a subfolder) and if it isn't we inform the user and exit. This has been working fine until a recent submission whereupon installing the app via TestFlight casuses it to be translocated when run and our check to fail. So, a couple of questions:
Is it expected that an app installed via TestFlight (or indeed the AppStore) can be translocated when it is run?
If yes to the above, how can we ensure that out app is running from Applications and can therefore activate its extensions?
Thanks
Alan
Hi! I am wondering about certain features that I witnessed today.
Base scenario: I created a developer certificate signed version of my installer package and then downloaded it via the internet. It has not been notarized.
As expected, macOS prevented the opening of the package, stating that it could not be determined whether it contained for malicious content.
But, several operations I then performed made this package trusted by macOS:
I moved the package through a file-sharing service via Finder, namely OneDrive. The recipient machine immediately opened the unsigned package, without any interruption from the operating system. This sounds extremely unsecure. I checked manually with xattr, and indeed, the com.apple.quarantine attribute has been removed on the recipient side.
I used pkgutil to explode the package, modified some files in it, then recompiled it. xattr again confirmed that the quarantine attribute has been removed. Why can pkgutil operate on untrusted packages?
I have personally been extremely surprised operations as simple as these remove security hurdles in macOS. These scenarios can be harmful for end-users who have little IT knowledge. Why are they allowed? Are these scenarios considered the responsibility of end-users? Why do we notarize and sign with precious distribution certificates if it's this simple to bypass any security check on macOS? :(