AppStore submission for Ruby/Glimmer app on MacOS without Xcode

Background

I've repeatedly run into codesigning (and missing provisioning profile) issues for my Ruby/Glimmer app and am looking for ways to troubleshoot this outside of Xcode. The app structure is as follows:

PATHmanager.app
└── Contents
    ├── Info.plist
    ├── MacOS
    │   └── PATHmanager
    ├── PkgInfo
    ├── Resources
    │   └── AppIcon.icns
    ├── _CodeSignature
    │   └── CodeResources
    └── embedded.provisionprofile

Architecture

I have a Mac mini Apple M2 Pro with macOS Ventura 13.4. Xcode is not used directly, but the underlying command line tools (e.g., codesign, productbuild, pkgutil, xcrun) are run from a custom Ruby script.

xcodebuild -version
Xcode 14.3.1
Build version 14E300c

Questions

  1. Is the .app directory and file structure/naming sufficient? If not, can you point me in the direction of a minimal example that does not use Xcode?

  2. Info.plist is an XML text document (not binary), which I believe is in an acceptable format, but how do I lint this file and determine if it contains all of the necessary key/value pairs?

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>en</string>
	<key>CFBundleDisplayName</key>
	<string>PATH manager</string>
	<key>CFBundleExecutable</key>
	<string>PATHmanager</string>
	<key>CFBundleIconFile</key>
	<string>AppIcon.icns</string>
	<key>CFBundleIdentifier</key>
	<string>com.chipcastle.pathmanager</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>PATHmanager</string>
	<key>CFBundlePackageType</key>
	<string>APPL</string>
	<key>CFBundleShortVersionString</key>
	<string>1.15</string>
	<key>CFBundleSupportedPlatforms</key>
	<array>
		<string>MacOSX</string>
	</array>
	<key>CFBundleVersion</key>
	<string>1.15</string>
	<key>ITSAppUsesNonExemptEncryption</key>
	<false/>
	<key>LSApplicationCategoryType</key>
	<string>public.app-category.developer-tools</string>
	<key>LSMinimumSystemVersion</key>
	<string>12.0</string>
	<key>LSUIElement</key>
	<false/>
	<key>NSAppTransportSecurity</key>
	<dict>
		<key>NSAllowsArbitraryLoads</key>
		<true/>
	</dict>
	<key>NSHumanReadableCopyright</key>
	<string>© 2025 Chip Castle Dot Com, Inc.</string>
	<key>NSMainNibFile</key>
	<string>MainMenu</string>
	<key>NSPrincipalClass</key>
	<string>NSApplication</string>
</dict>
</plist>
  1. PATHmanager is a Mach-O 64-bit executable arm64 file created by using Tebako. Does this executable need to be codesigned, or is codesigning the .app folder sufficient?

  2. Does the .app directory need an entitlements file? Here's how I codesign it:

codesign --deep --force --verify --verbose=4 --options runtime --timestamp --sign 'Apple Distribution: Chip Castle Dot Com, Inc. (BXN9N7MNU3)' '/Users/chip/Desktop/distribution/PATHmanager.app'
  1. Does the PATHmanager binary need an entitlements file? Here's how I codesign it:
codesign --deep --force --verify --verbose=4 --options runtime --timestamp --entitlements '/Users/chip/Desktop/PATHmanager.entitlements' --sign 'Apple Distribution: Chip Castle Dot Com, Inc. (BXN9N7MNU3)' '/Users/chip/Desktop/distribution/PATHmanager.app/Contents/MacOS/PATHmanager'

  1. How can I verify what entitlements, if any, are required for codesigning the binary? The PATHmanager.entitlements file is an XML text file containing only the following:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.security.app-sandbox</key>
    <true/>
</dict>
</plist>
  1. Is the embedded.provisionprofile necessary, and if so, how do I know determine if it matches the certificate or entitlements that I'm using? Additionally, is it named and located properly?

  2. I submitted this to the AppStore several weeks ago and the reviewer reported that the executable would not load on their machine (even though it worked on mine.) Is it better for me to release via TestFlight for testing, and if so, do I need to following a separate process for codesigning (i.e., using different entitlements, profiles, certs, etc) when doing so?

I've been playing whack-a-mole with this for too long to mention and am hoping to nail down a better deployment flow, so any suggestions for improvement will be greatly appreciated. Thank you in advance.

The easiest solution is to setup a demo Xcode app with the same name and bundleID and see how Xcode does it. Deviate at your peril.

If you're trying to roll your own app, I recommend consulting all of the existing documentation first. A good place to start would be --deep Considered Harmful

Also, Apple now requires Xcode 15 for App Store submissions. See this news post.. So even if you aren't building and submitting with Xcode 15, you would want to use Xcode 15 to build that demo template app. Xcode 15 does work on Ventura. However, that update was over a year ago now. Apple could change this requirement "any day now".

You should really be testing on a pristine system that has never seen Xcode or your app before. You may be able to use a VM for this.

@Etresoft Thank you for your prompt reply. I tried upgrading to Xcode 15, but the AppStore would only let me download version 14. I uninstalled Xcode, but afterwards it only offers version 16 and reports, "Requires macOS 14.5 or later.", which means I need to upgrade to Sonoma. Do you have another suggestion for downloading version 15 on Ventura? Thanks again.

Never download Xcode from the App Store. Always download it directly from the developer site. You can download Xcode 15 there too.

Thanks for the suggestion. I downloaded Xcode_15.xip, but opening reports, "You can't use this version of the application Xcode with this version of macOS."

Is the .app directory and file structure/naming sufficient?

It looks reasonable enough. A good place to start with this stuff is Placing Content in a Bundle. If you need more info then create a test project in Xcode, build it, and see what it did.

how do I lint this file … ?

You can lint it with plutil. Indeed, I recommend you do that.

Actually, my general advice is that you use plutil to convert it to the XML format, which means it’s not just technically correct but in the canonical format.

and determine if it contains all of the necessary key/value pairs?

It’s hard to answer that, because it depends what you app does. However, a good place to start is with the above-mentioned Xcode project.

is codesigning the .app folder sufficient?

This is answered by Creating distribution-signed code for macOS. I recommend that you follow the advice there, and in Packaging Mac software for distribution.

Does the .app directory need an entitlements file?

The file itself? No. Entitlements are baked into the program when you sign it. So you might need an .entitlements file as an input to codesign, but you don’t need to include that specific file in your app.

As to whether you need entitlements at all, that very much depends. See below.

Here's how I codesign it:

Don’t use --deep. See --deep Considered Harmful.

How can I verify what entitlements, if any, are required for codesigning the binary?

There’s no single answer to that question. It depends on what your code does.

However, if you’re distributing on the App Store then, yes, you definitely need the entitlement that enables the App Sandbox.

Also, if you plan to use TestFlight, which you should, see TestFlight, Provisioning Profiles, and the Mac App Store.

Is the embedded.provisionprofile necessary

Only if your app uses restricted entitlements. The App Sandox entitlement is not restricted, but the TestFlight ones are.

how do I know determine if it matches the certificate or entitlements that I'm using?

TN3125 Inside Code Signing: Provisioning Profiles explains that in gory detail.

Additionally, is it named and located properly?

This is another thing covered by Placing Content in a Bundle.

Is it better for me to release via TestFlight for testing

Yes. And that does complicate things somewhat, as I mentioned above.


The easiest solution is to setup a demo Xcode app with the same name and bundleID and see how Xcode does it.

This is good advice IMO.

You can both look at the output and also look build transcript to work out how Xcode created that output.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thanks for the suggestion. I downloaded Xcode_15.xip, but opening reports, "You can't use this version of the application Xcode with this version of macOS."

Sorry, according to Xcode support page, Xcode 15 requires macOS 13.5.

Making progress here:

  1. Upgraded to Sequoia 15.3.1, Xcode 16.2

  2. Codesigning executable returns 'satisfies its Designated Requirement' using:

codesign --force --verify --verbose=4 --options runtime --timestamp --entitlements '/Users/chip/Desktop/PATHmanager.entitlements' --sign 'Apple Distribution: Chip Castle Dot Com, Inc. (BXN9N7MNU3)' '/Users/chip/Desktop/distribution/PATHmanager.app/Contents/MacOS/PATHmanager'

  1. Productbuild .pkg file returns successfully using:

productbuild --sign '3rd Party Mac Developer Installer: Chip Castle Dot Com, Inc. (BXN9N7MNU3)' --identifier 'com.chipcastle.pathmanager' --version '1.15' --component '/Users/chip/Desktop/distribution/PATHmanager.app' /Applications '/Users/chip/Desktop/PATHmanager.pkg'

  1. Verifying signature returns 'satisfies its Designated Requirement' using:

codesign --verify --verbose=4 '/Users/chip/Desktop/distribution/PATHmanager.app/Contents/MacOS/PATHmanager'

  1. Transporter uploads successfully.
  2. Running Verify via Transporter returns error: 'Invalid Provisioning Profile Signature'
  3. Other forum posters recommended regenerating a new profile and certificates, which I did using Xcode, and then downloading the profile again. I tried numerous times, but the same error persists via Transporter.

I read 'TN3125: Inside Code Signing: Provisioning Profiles', which mostly covers how to inspect the contents of the profile, but not how to troubleshoot errors. Any suggestions on how to drill down further with this error is appreciated. Thanks.

I’m glad to hear your making progress.

Regarding your provisioning profile issue, remember that a provisioning profile ties together a bunch of items, including the certificate from the code-signing identity used to sign the code. Given that, a distribution profile must necessarily be different from a development profile, because a distribution certificate is different from a development certificate. So, when you re-sign a development-signed app with your distributing signing identity, you have to first replace its development profile with your distribution profile.

Creating distribution-signed code for macOS covers this in its Embed distribution provisioning profiles section.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thanks, I just copied my distribution profile to PATHmanager.app/Contents/embedded.provisionprofile, re-signed the .app bundle and executable, and uploaded the pkg file using Transporter, which returns:

Show Progress: Verify failed.
Validation failed
Invalid Code Signing. The executable 'com.chipcastle.pathmanager.pkg/Payload/PATHmanager.app/Contents/MacOS/PATHmanager' must be signed with the certificate that is contained in the provisioning profile. (ID: 1810bc78-dcce-483f-b641-239894446e0d)

I'm confused. How I can match up the profile (shown below) with the cert? Thanks again.

security find-identity -v

  1. B9C100CC75910543E3FCD9AE63357AE4E2736723 "Apple Development: Harroll Dean Castle (76CZ7DC9QM)"

  2. D67F1D2EE9FC682B0BDAFDA1924936335C6E7595 "Apple Distribution: Chip Castle Dot Com, Inc. (BXN9N7MNU3)"

  3. D99EF2166A4F18DC4DA375C39F20F3DF2656E841 "3rd Party Mac Developer Installer: Chip Castle Dot Com, Inc. (BXN9N7MNU3)"

    3 valid identities found

How I can match up the profile (shown below) with the cert?

TN3125 Inside Code Signing: Provisioning Profiles explains how to extract the certificates that are authorised by a profile. See The who section.

TN3161 Inside Code Signing: Certificates explains how to extract the certificate chain from a code signature. See the Chain of trust section.

I recommend that you do both and then check whether the certificate list in the profile contains the leaf certificate from the code’s certificate chain.

IMPORTANT Don’t rely on the common name in the certificate. Rather, look at the issuer and the serial number. Those are the properties that uniquely identify a certificate.

Or just compare the certificates byte-for-byte [1]. Or use shasum to generate a SHA-1 checksum for both certificates. The latter is handy because it aligns with the output from find-identity.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] This works because ASN.1 DER rules mean that there’s only one correct way to encode a certificate.

1. Unpack profile:

security cms -D -i distribution/PATHmanager.app/Contents/embedded.provisionprofile -o profile.plist

(attached profile.plist)

2. Extract the cert chain:

codesign --display --extract-certificates distribution/PATHmanager.app
openssl x509 -in codesign0 -inform der -text > leaf

(attached leaf)

3. Serial number for leaf:

λ head leaf         
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            4a:9a:24:59:ac:96:e8:e8:45:f6:71:ab:59:b8:69:32
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN=Apple Worldwide Developer Relations Certification Authority, OU=G3, O=Apple Inc., C=US
        Validity
            Not Before: Mar  1 00:37:19 2025 GMT
            Not After : Mar  1 00:37:18 2026 GMT

4. What part of the profile should I compare to the leaf serial number?

λ shasum leaf
ce0e2fc70a9bde62745332b843ef650a918a39dc  leaf

I extracted the DeveloperCertificates property from the profile.plist you posted:

% cat profile-cert.b64                               
MIIF4TCCBMmgAwIBAgIQPWaGoIfFiyPRVIqVv2CUkDANBgkqhkiG9w0BAQsFADB1MUQwQgYD…

I then Base64 decoded it:

% base64 -d < profile-cert.b64 > profile-cert.der

And dumped it with openssl:

% openssl x509 -in profile-cert.cer -inform der -text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            3d:66:86:a0:87:c5:8b:23:d1:54:8a:95:bf:60:94:90
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN=Apple Worldwide Developer Relations Certification Authority, OU=G3, O=Apple Inc., C=US

The issuer is correct but the serial number is different from the leaf example you posted.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thanks for detailed commands! That really helped.

  1. I found the matching profile, copied it over to embedded.provisionprofile, resigned the executable & bundle, and uploaded using Transporter.
  2. Received "missing an application identifier" error and fixed it from https://developer.apple.com/forums/thread/748589?login=true and TestFlight, Provisioning Profiles, and the Mac App Store
  3. Uploaded & Validated w/ Transporter, but received an email about:
ITMS-91109: Invalid package contents - The package contains one or more files with the com.apple.quarantine extended file attribute, such as “com.chipcastle.pathmanager.pkg/Payload/PATHmanager.app/Contents/embedded.provisionprofile”. This attribute isn’t permitted in macOS apps distributed on TestFlight or the App Store. Please remove the attribute from all files within your app and upload again.
  1. Attempted to remove extended attributes as follows (sudo had no effect):
~/Desktop/distribution/PATHmanager.app/Contents
λ xattr embedded.provisionprofile                  
com.apple.macl

~/Desktop/distribution/PATHmanager.app/Contents
λ xattr -c embedded.provisionprofile               

~/Desktop/distribution/PATHmanager.app/Contents
λ xattr embedded.provisionprofile   
com.apple.macl

~/Desktop/distribution/PATHmanager.app/Contents
λ xattr -d com.apple.macl embedded.provisionprofile

~/Desktop/distribution/PATHmanager.app/Contents
λ xattr embedded.provisionprofile                  
com.apple.macl

~/Desktop/distribution/PATHmanager.app/Contents
λ ls -l@ embedded.provisionprofile                         
-rw-r--r--@ 1 chip  staff  12303 Feb 28 18:57 embedded.provisionprofile
	com.apple.macl	  72 

~/Desktop/distribution/PATHmanager.app/Contents
λ xattr -d com.apple.macl:72 embedded.provisionprofile
xattr: embedded.provisionprofile: No such xattr: com.apple.macl:72

~/Desktop/distribution/PATHmanager.app/Contents
λ sudo xattr -d com.apple.macl:72 embedded.provisionprofile     
Password:
xattr: embedded.provisionprofile: No such xattr: com.apple.macl:72

~/Desktop/distribution/PATHmanager.app/Contents
❮ sudo xattr -d com.apple.macl embedded.provisionprofile 

~/Desktop/distribution/PATHmanager.app/Contents
λ ls -l@ embedded.provisionprofile                    
-rw-r--r--@ 1 chip  staff  12303 Feb 28 18:57 embedded.provisionprofile
	com.apple.macl	  72 

I've had no trouble using xattr before, so not sure what's happening here. Suggestions are appreciated. Thanks in advance.


~/Desktop/distribution/PATHmanager.app/Contents

λ xattr -d com.apple.quarantine embedded.provisionprofile 

xattr: embedded.provisionprofile: No such xattr: com.apple.quarantine

I have used ack and xattr in an attempt to find where the com.apple.quarantine attribute might exist, but have not found it in the .pkg file I uploaded using Transporter or in any files contained in the .pkg bundle.

It sounds like you’re making really good progress. Now let’s see if we can get you over this quarantine extended attribute hurdle.

Consider this tiny test app:

% find "Test774923.app"
Test774923.app
Test774923.app/Contents
Test774923.app/Contents/_CodeSignature
Test774923.app/Contents/_CodeSignature/CodeResources
Test774923.app/Contents/MacOS
Test774923.app/Contents/MacOS/Test774923
Test774923.app/Contents/Resources
Test774923.app/Contents/Resources/MainMenu.nib
Test774923.app/Contents/Info.plist
Test774923.app/Contents/PkgInfo

Let’s deliberately quarantine one of its files:

% QQuarantine add "Test774923.app/Contents/Resources/MainMenu.nib"

Note QQuarantine is a tool I wrote that quarantines an item by setting the .quarantinePropertiesKey property. If you wanna replicate these exact steps, you can write your own tool to do this, or just upload a file to a website and download it with Safari.

Next we bundle it up into an installer package:

% productbuild --sign "3rd Party Mac Developer Installer" --component "Test774923.app" /Applications "Test774923.pkg"
productbuild: Adding component at …/Test774923.app
productbuild: Signing product with identity "3rd Party Mac Developer Installer…
…
productbuild: Wrote product to Test774923.pkg
productbuild: Supported OS versions: [Min: 12.0, Before: None]

Now we’re gonna unpack that and look for the problematic file. We start by unpacking the installer itself, using the instructions from Unpacking Apple Archives:

% mkdir tmp
% cd tmp
% xar -xf "../Test774923.pkg"

Now let’s list the BOM:

% lsbom "com.example.apple-samplecode.Test774923.pkg/Bom"
. …
./Test774923.app …
./Test774923.app/Contents …
./Test774923.app/Contents/Info.plist …
./Test774923.app/Contents/MacOS …
./Test774923.app/Contents/MacOS/Test774923 …
./Test774923.app/Contents/PkgInfo …
./Test774923.app/Contents/Resources …
./Test774923.app/Contents/Resources/._MainMenu.nib …
./Test774923.app/Contents/Resources/MainMenu.nib …
./Test774923.app/Contents/_CodeSignature …
./Test774923.app/Contents/_CodeSignature/CodeResources …

Observe that MainMenu.nib has an AppleDouble file, ._MainMenu.nib. That’s a concern. In rare circumstances it might make sense to ship Mac software with extended attributes or other bits of Mac metadata that require an AppleDouble file. However, in the majority of cases, apps should not have any such metadata, and thus app installer packages should contain zero AppleDouble files.

Note For an explanation of what an AppleDouble file is, see Extended Attributes and Zip Archives.

Let’s unpack the app itself and see why that file has an AppleDouble:

% cpio -i < "com.example.apple-samplecode.Test774923.pkg/Payload" 
180 blocks
% xattr "./Test774923.app/Contents/Resources/MainMenu.nib"
com.apple.quarantine

Et voilà!

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Interesting info. Thank you for that. More progess...

Find quarantine attribute

/tmp
λ xar -xf ~/Desktop/PATHmanager.pkg

/tmp
λ lsbom "com.chipcastle.pathmanager.pkg/Bom" 
.	0	0/0
./._PATHmanager.app	40755	0/0	0	0
./PATHmanager.app	40755	0/0
./PATHmanager.app/Contents	40755	0/0
./PATHmanager.app/Contents/._embedded.provisionprofile	100644	0/0	0	0
./PATHmanager.app/Contents/Info.plist	100644	0/0	1415	2301784519
./PATHmanager.app/Contents/MacOS	40755	0/0
./PATHmanager.app/Contents/MacOS/PATHmanager	100755	0/0	856344832	790394002
./PATHmanager.app/Contents/PkgInfo	100644	0/0	8	742937289
./PATHmanager.app/Contents/Resources	40755	0/0
./PATHmanager.app/Contents/Resources/AppIcon.icns	100644	0/0	56310	2265036908
./PATHmanager.app/Contents/_CodeSignature	40755	0/0
./PATHmanager.app/Contents/_CodeSignature/CodeResources	100644	0/0	2593	45803994
./PATHmanager.app/Contents/embedded.provisionprofile	100644	0/0	12303	521235782

/tmp
λ cpio -i < "com.chipcastle.pathmanager.pkg/Payload" 
1672695 blocks

/tmp
λ xattr PATHmanager.app                                      
com.apple.macl

/tmp
λ xattr PATHmanager.app/Contents/embedded.provisionprofile   
com.apple.macl
com.apple.metadata:kMDItemWhereFroms
com.apple.provenance
com.apple.quarantine

Remove quarantine attribute

/tmp
λ xattr -d com.apple.quarantine PATHmanager.app/Contents/embedded.provisionprofile 

/tmp
λ xattr PATHmanager.app/Contents/embedded.provisionprofile                        
com.apple.macl
com.apple.metadata:kMDItemWhereFroms
com.apple.provenance

Bump version number in Info.plist to 1.16 and build

/tmp 9s
❮ productbuild --sign '3rd Party Mac Developer Installer: Chip Castle Dot Com, Inc. (BXN9N7MNU3)' --identifier 'com.chipcastle.pathmanager' --version '1.16' --component '/tmp/PATHmanager.app' /Applications '/Users/chip/Desktop/PATHmanager.pkg'
productbuild: Adding component at /tmp/PATHmanager.app
productbuild: Signing product with identity "3rd Party Mac Developer Installer: Chip Castle Dot Com, Inc. (BXN9N7MNU3)" from keychain /Users/chip/Library/Keychains/login.keychain-db
productbuild: Adding certificate "Apple Worldwide Developer Relations Certification Authority"
productbuild: Adding certificate "Apple Root CA"
productbuild: Wrote product to /Users/chip/Desktop/PATHmanager.pkg
productbuild: Supported OS versions: [Min: 12.0, Before: None]

Transporter reports sandbox error

Validation failed App sandbox not enabled. The following executables must include the "com.apple.security.app-sandbox" entitlement with a Boolean value of true in the entitlements property list: [( "com.chipcastle.pathmanager.pkg/Payload/PATHmanager.app/Contents/MacOS/PATHmanager" )] Refer to App Sandbox page at https://developer.apple.com/documentation/security/app_sandbox for more information on sandboxing your app. (ID: 7a687ea9-a98d-40f2-9553-ecce05ba6e87)

Verify sandbox entitlement (see attached file)

Not sure what to do here.

Transporter reports sandbox error

Probably like this are usually caused by one of two things:

  • The program is not actually sandboxed.

  • It has a broken code signature that prevents App Store Connect from checking its entitlements.

You posted the .entitlements file but that’s not what matters here. It’s source code, and App Store Connection is checking your binary. You need to verify that, after installation, the program’s code signature is valid and that it includes the App Sandbox entitlement. So, something like:

% codesign -v --deep --strict "PATHmanager.app"
% codesign -d --entitlements - "PATHmanager.app"

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thank you for the update. Here's the output:

λ codesign -v --deep --strict "PATHmanager.app"
PATHmanager.app: invalid Info.plist (plist or signature have been modified)
In architecture: arm64

/tmp
λ codesign -d --entitlements - "PATHmanager.app"
Executable=/private/tmp/PATHmanager.app/Contents/MacOS/PATHmanager
[Dict]
	[Key] com.apple.application-identifier
	[Value]
		[String] BXN9N7MNU3.com.chipcastle.pathmanager
	[Key] com.apple.developer.team-identifier
	[Value]
		[String] BXN9N7MNU3
	[Key] com.apple.security.app-sandbox
	[Value]
		[Bool] true

It looks like the entitlement is ok. I'm still wrestling with what is specifically making Info.plist invalid, though.

PATHmanager.app: invalid Info.plist (plist or signature have been modified)

Well, that’s not good. The most obvious cause of this problem is that your Info.plist has changed after the code was signed, which breaks the seal on the code signature. For example:

% codesign -v --deep --strict "QProcessDock.app"
% plutil -insert "Greeting" -string 'Hello Cruel World!' "QProcessDock.app/Contents/Info.plist" 
% codesign -v --deep --strict "QProcessDock.app"                                               
QProcessDock.app: invalid Info.plist (plist or signature have been modified)
In architecture: arm64

It’s possible that you might see this for other reasons — like codesign being confused by whether the item you’re signing is a bundle or not — but that seems unlikely given that your bundle structure seems reasonable based on the info you’ve posted upthread.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I think I'm closing in on a solution. Here's what I did to get here:

1. Removed all development gems from Gemfile & bundled

bundle install --without development test

This removed the date gem, which was the original complaint by macOS, along with other gems (i.e., psych, rdoc, debug).

2. Created executable

tebako clean && tebako press --root=/Users/chip/code/ruby/pathos_macos --entry-point=/Users/chip/code/ruby/pathos_macos/bin/pathos_macos -o ~/Desktop/pathos

3. Copied over executable to .app folder

cp ~/Desktop/pathos ~/Desktop/distribution/PATHmanager.app/Contents/MacOS/PATHmanager

4. Fixed ownerships (needs further investigation)

chown -R chip:staff ~/Desktop/distribution

5. Bumped version number manual file edit in Info.plist & appstore.rb (codesigning script)

6. Ran codesigning script

~/code/ruby/pathos_macos/assets/appstore.rb

7. Uploaded package via Transporter

Located at (~/Desktop/PATHmanager.pkg)

8. Test with TestFlight

I had to remove myself from QA/Testers on AppStore Connect and then add myself back for it to update the version properly.

9. Discovered error

“libui.dylib” can’t be opened because it was not downloaded from the App Store

10. Clicked "Show in Finder"

This created ~/Library/Containers/com.chipcastle.pathmanager/Data/tmp/tebako-runtime-20250313-19572-kgrc66 which had a quarantine attribute. I removed it with xattr -d com.apple.quarantine tebako-runtime-20250313-19572-kgrc66 but then the folder was automatically removed.

Do you have any suggestions on getting libui.dylib to be accepted? Thanks!

More progress. Cool.

Do you have any suggestions on getting libui.dylib to be accepted?

That depends on where this library is coming from. The Mac App Store re-signs your code as part of the distribution process. For this to work it has to be able to ‘see’ your code. Based on the steps you posted, I suspect that’s not the case here. Rather, I suspect that tebako press is creating some sort of self-extracting executable, that is, an executable that, when you run it, unpacks a copy of the Ruby runtime and uses that to run your code.

The problem with this approach is that the App Store can’t see the libraries that are packed into this runtime, and thus can’t re-sign them.

Now, in a directly distributed app you can get around this by pre-signing and pre-notarising such libraries. It’s a hassle, but it works. However, that won’t work for the Mac App Store. It has to be able to see the libraries in order to do its re-sign.

Unfortunately, this is kinda where I leave you. You need to find a way to convince tebako to leave any native code out of the archive so that you can include it in the standard place within your bundle. For a dynamic library that’d be Contents/Frameworks [1]. I’ve no idea if the tool can do that. That’s something you’d have to escalate via the tool’s support channel.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] For other content, see Placing Content in a Bundle.

Thanks for the suggestion. I was able to extract libui.dylib by running bundle install with the following configuration:

cat ~/code/ruby/pathos_macos/.bundle/config                            
---
BUNDLE_PATH: "vendor/"
BUNDLE_WITHOUT: "development:test"

This created vendor/ruby/3.3.0/gems/libui-0.1.2-arm64-darwin/vendor/libui.dylib, which I ditto'd over to ~/Desktop/distribution/PATHmanager.app/Contents/Frameworks/libui.dylib

I bumped version (as described previously) and ran my codesigning script which signs in the following order (under /Users/chip/Desktop/distribution/PATHmanager.app/):

  1. Contents/Frameworks/libui.dylib
  2. Contents/MacOS/PATHmanager
  3. PATHmanager.app directory

After uploading the .pkg file using Transporter, I get this old error:

Validation failed (409)
App sandbox not enabled. The following executables must include the "com.apple.security.app-sandbox" entitlement with a Boolean value of true in the entitlements property list: [( "com.chipcastle.pathmanager.pkg/Payload/PATHmanager.app/Contents/MacOS/PATHmanager" )] Refer to App Sandbox page at https://developer.apple.com/documentation/security/app_sandbox for more information on sandboxing your app. (ID: dce05eba-fbda-496f-b0fb-31e85eee0152)

It's the same entitlements file that I've been using, which does include the com.apple.security.app-sandbox entitlement, so I continue to be puzzled. I'll look into this further and post any updates or progress I've made.

Thank you for your continued support. It has been greatly appreciated.

ran my codesigning script which signs in the following order

Step 2 is unnecessary here. Using the terms from Creating distribution-signed code for macOS, your app is bundled code. That means you only need to sign the bundle. If you sign the PATHmanager executable separately, that signature is just overwritten when you sign the PATHmanager.app.

so I continue to be puzzled

That error is misleading, in that there are two potential causes:

  • The executable is missing this entitlement.

  • The executable’s code signature is broken, which means that App Store Connect is unable to check that the entitlement is present.

I suspect you’re hitting the second case.

If you unpack the installer [1] and check the app’s code signature like so:

% codesign --verify -vvv "PATHmanager.app"

what does it report?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] I use Pacifist for this, but you can do it with Apple tools. See Unpacking Apple Archives.

AppStore submission for Ruby/Glimmer app on MacOS without Xcode
 
 
Q