“a sealed resource is missing or invalid” on an installed, notarized application

We have a native ARM64 application. The application is a development environment and native compiler for the language Common Lisp. CL has a foreign function interface, which allows loading of .dylib files into CL and calling functions in them from CL. For this reason, we add certain entitlements. See below.

It is notarized and installed on macOS 14.7. When I run spctl on it I get this:

$ spctl --assess -v /Applications/AllegroCL64.app
/Applications/AllegroCL64.app: rejected (the code is valid but does not seem to be an app)

That’s before I run it. Which is odd because the app is notarized. When I run the app, it asks for a license file and installs it into /Applications/AllegroCL64.app/Contents/Resources/ and after that, the spctl shows this:

$ spctl --assess -v /Applications/AllegroCL64.app /Applications/AllegroCL64.app: a sealed resource is missing or invalid

I assume the mere act of copying the license (a file called devel.lic which is a small text file) is causing this. Why does it say it “does not seem to be an app”?

This self-modification of the files in the Contents/Resources directory is a huge feature. We allow downloading of patches, which add features and fix bugs in the product. Is this going to be a problem, going forward? I don’t remember seeing this result from spctl before and I have a feeling it’s a new , due to tightening of security policies, etc.

All of this is quite worrying to us.

More details of the app:

$ codesign -vvvv mlisp
mlisp: valid on disk
mlisp: satisfies its Designated Requirement
$ codesign -d --entitlements - /Applications/AllegroCL64.app
Executable=/Applications/AllegroCL64.app/Contents/MacOS/AllegroCL64
[Dict]
    [Key] com.apple.security.cs.allow-dyld-environment-variables
    [Value]
        [Bool] true
    [Key] com.apple.security.cs.allow-jit
    [Value]
        [Bool] true
    [Key] com.apple.security.cs.disable-library-validation
    [Value]
        [Bool] true
    [Key] com.apple.security.get-task-allow
    [Value]
        [Bool] true
$ 

Other details:

  • The app was built with the Command Line tools version 2395 on macOS 12.x.

I assume the mere act of copying the license (a file called devel.lic which is a small text file) is causing this.

Yes. Any change to the application bundle after signing could trigger this. I think there are ways to validate a signature while accepting a certain level of irregularity. But you don't have any control over how the OS on an end user's system is going to perform the validation. And those validation strategies will likely change as the OS evolves. The best course of action is to always assume the bundle never changes.

There are many alternative places to store licensing information. I recommend keeping it in the user's home directory so you don't have to ask the user for admin privileges to create it.

Why does it say it “does not seem to be an app”?

Most likely the bundle structure diverges too far from what is expected.

Remember that the purpose of all of this is to detect and block malware, which often uses novel ways to structure bundles and executables. The idea is to exploit edge cases that Apple never anticipated in order to confuse the system and gain more privileges. The more unusual your app is structured, the more likely you are to be impacted. This can happen during development or at an unexpected time later on.

This self-modification of the files in the Contents/Resources directory is a huge feature. We allow downloading of patches, which add features and fix bugs in the product. Is this going to be a problem, going forward?

Yes.

In theory, it's possible to modify parts of the application bundle and then supply an updated signature that matches the new bundle. But I'm not sure if anyone has ever managed to do that successfully. It's a high-risk, high-effort solution when storage and bandwidth are cheap.

Furthermore, you shouldn't be putting patches or executable code in the Resources directory. That is a special location for non-executable resource data. Using it for any kind of executable code is an excellent way to give yourself signing and/or notarization problems.

@Etresoft thanks for the reply.

How do applications patch themselves and still not run afoul of Gatekeeper, then? Are they just complete reinstalls?

Allegro Common Lisp is 35+ years old. We have a customers with a huge amount of history. We have been using our patching system for decades. Sounds like Apple is saying we must throw that away, because the patches do include binary executables (shared libraries), though they are code signed.

Moving everything that changes outside of Contents/Resources will mean either it's user specific, or we'll need to use /Library/Application Support/, which will require admin privs. Also, it's quite a lot of redesign for us to move everything out.

As for the "not an app" ... I mean, Apple notarized our app and didn't complain then. Seems like I should have gotten errors or warnings for that.

How do applications patch themselves and still not run afoul of Gatekeeper, then? Are they just complete reinstalls?

I can't speak for all applications. For me personally, life is complicated enough as it is.

You can definitely patch your application bundle, but one of the files you replace should be the signature. And that signature will have to be valid for the application bundle as it is on (the user's) disk.

Apple is saying we must throw that away, because the patches do include binary executables (shared libraries), though they are code signed.

I'm not making any statements about Apple. My position is that it's better to maintain a valid, signed, notarized bundle on disk. I'm confident that this will result in an easier, more trouble free experience for both the user and the developer. I've definitely seen developers use different methods. I just can't recommend those other approaches.

Patching the app bundle is not any kind of violation or anything. It's just tricky, prone to failure, and creates the potential for a significant problem later on, when you are least prepared to deal with it.

From what I've learned with my own app, I can tell you that Apple has, so far, been very conservative with respect to signature validation. Lots of developers find it challenging to get past Gatekeeper. But once they get installed, they can pretty much do whatever they want. It might not always be that way.

Moving everything that changes outside of Contents/Resources will mean either it's user specific, or we'll need to use /Library/Application Support/, which will require admin privs. Also, it's quite a lot of redesign for us to move everything out.

That's not what I said. I said that the Resources directory should be for non-executable data - images, text files, translations, data files, whatever. But it's not the place for executable binaries or libraries.

Ideally, nothing should be changing. But if you do want to make changes, you can change anything. It's just that the signature should match.

There is a version of "Library/Application Support" available in the user's home directory. If you need a place for dynamic source code, plug-ins, libraries, etc., that would be the place for it. I'm not familiar with your code. And I'm not familiar with apps that scatter components around. There might be better locations than "Application Support". There is also a "Frameworks" directory, for example.

Apple notarized our app and didn't complain then. Seems like I should have gotten errors or warnings for that.

Notarization is used for more than just apps. One mistake I see a lot in this forum is assuming that a successful result from the command-line notarization tools means that notarization was successful. It's not successful until it runs in a pristine environment like a VM.

“a sealed resource is missing or invalid” on an installed, notarized application
 
 
Q