Notarize Apple binaries
Notarization is the process of scanning Developer ID-signed software for malicious components before distribution outside of the Mac App Store. To , follow the procedures in this article.
Follow these instructions to notarize your Apple binaries with Signing Manager Controller (SMCTL) using notarytool or altool.
Tip
As of November 1, 2023, altool will no longer be supported by Apple Notary Service. Use notarytool to notarize your software to avoid disruption of service.
What is Apple Notary Service?
The Apple Notary Service is an automated system that scans your software for malicious content, checks for code-signing issues, and returns the results to you quickly. If no issues are detected in the scan, the notary service generates a ticket for you to staple to your software. The notary service also publishes that ticket online where Gatekeeper can find it.
Why should I notarize my software?
When a user first installs or runs your software, the presence of a ticket (either online or attached to the executable) tells Gatekeeper that Apple notarized the software. Gatekeeper then places descriptive information in the initial launch dialog to help the user make an informed choice about whether to launch the app.
Prerequisites
macOS
Note
notarytool and altool is provided as part of the macOS.
Xcode command Utility
Apple credentials for notarization
Create one of the following Apple credentials based on the notarization tool you want to use.
Save your Apple credentials to Keychain
Use the following one of the following commands to save your credentials to Keychain.
Tip
The profile name you give your credentials in Keychain will be used in notarization commands.
Notarize
Notarization produces a ticket that tells Gatekeeper that your app is notarized. After notarization completes, when a user attempts to run your app on macOS 10.14 or later, Gatekeeper will find the ticket online.
Note
Before notarization, the binary must be:
Signed
Provided in one of the following formats:
.pkg
.dmg
.zip
(Compress .app binaries into a .zip)
The notarize command below will:
Notarize your binary.
Upload your binary to Apple notary Server (this may take a while).
Once uploaded, the notary server will provide you with the submission ID.
Tip
The submission ID is used to check the status and log of the notarization.
Notarization status
After you upload your file, the notarization process typically takes less than an hour. To check the status of the request, follow one of the procedures outlined below.
Note
Notarization ID is the Software Trust Manager server notarization ID.
Submission ID is the NotaryServer ID provided after the file was successfully uploaded.
Notarization logs
The notary log is a key tool for debugging notarization and trusted execution issues. Check the notarization logs for information on why notarization failed, to check for warnings, and to confirm that all your code was included in the notarized ticket.
Note
Notarization logs are only available in notarytool. Always check the log file, even if notarization succeeds, because it might contain warnings that you can fix prior to your next submission.
To check the logs created by Notary Server:
smctl-mac-x64 notarization log --tool notarytool <notarization ID or submission ID> --profile-name <Keychain credentials profile name> -v
Command sample:
smctl-mac-x64 notarization log --tool notarytool 5cb03d00-8ab1-4fdc-bb0a-f4167dc01f03 --profile-name <Keychain credentials profile name> -v
Command output:
{ "logFormatVersion": 1, "jobId": "5cb03d00-8ab1-4fdc-bb0a-f4167dc01f03", "status": "Accepted", "statusSummary": "Ready for distribution", "statusCode": 0, "archiveFilename": "example.dylib.dmg", "uploadDate": "2023-04-17T06:34:20.469Z", "sha256": "74c81b1fe123d994e56e153833896302d4d9398a6b0a3f3f5518e8b86393db6", "ticketContents": [ { "path": "example.dylib.dmg", "digestAlgorithm": "SHA-256", "cdhash": "5fa62fc5f5bec1f2b1464adc0d203393c0994cef" }, { "path": "example.dylib.dmg/example.dylib", "digestAlgorithm": "SHA-256", "cdhash": "76e7cbde3fb5434d015a22b4eccdea567e44a25b", "arch": "x86_64" } ], "issues": null } logsCommand command was SUCCESSFUL a7abfd6f-6367-443e-96a6-ab7dff751447 ID: a7abfd6f-6367-443e-96a6-ab7dff751447 SUBMISSION ID: 5ad03d00-8ab1-4fdc-bb0a-f4167dc01f03 SIGNATUREID: CREATED ON:2023-04-17 06:34:20 +0000 UTC CREATED BY:stm user MODIFIED ON:2023-04-17 06:37:27 +0000 UTC MODIFIED BY:stm user ACCOUNT ID:f28bd2a7-4762-1111-b40b-826ea4b1b3e4 LOG: Tool Used: notarytool Timestamp:2023-04-17 06:37:27.506724 +0000 UTC log: { "logFormatVersion": 1, "jobId": "5cb03d00-8ab1-4fdc-bb0a-f4167dc01f03", "status": "Accepted", "statusSummary": "Ready for distribution", "statusCode": 0, "archiveFilename": "example.dylib.dmg", "uploadDate": "2023-04-17T06:34:20.469Z", "sha256": "40c81b1fe9528d994e56e153833896302d4d9398a6b0a3f3f5518e8b86393db6", "ticketContents": [ { "path": "example.dylib.dmg", "digestAlgorithm": "SHA-256", "cdhash": "5fa62fc5f5bec1f2b1464adc0d203393c0994cef" }, { "path": "example.dylib.dmg/example.dylib", "digestAlgorithm": "SHA-256", "cdhash": "76e7cbde3fb5434d015a22b4eccdea567e44a25b", "arch": "x86_64" } ], "issues": null } Tool Used: notarytool Timestamp:2023-04-17 06:36:34.874059 +0000 UTC log: {"status":"Accepted","id":"5cb03d00-8ab1-4fdc-bb0a-f4167dc01f03","createdDate":"2023-04-17T06:34:17.574Z","message":"Successfully received submission info","name":"example.dylib.dmg"} Tool Used: notarytool Timestamp:2023-04-17 06:34:20.706515 +0000 UTC log: {"path":"\/Users\/john.doe\/Documents\/testing\/example.dylib.dmg","id":"5cb03d00-8ab1-4fdc-bb0a-f4167dc01f03","message":"Successfully uploaded file"}
Staple
Staple to attach the ticket to your software using the stapler tool. This ensures that future distributions include the ticket and that Gatekeeper can find the ticket even when a network connection isn’t available.
Note
Before stapling the ticket, binaries must be:
Signed
Notarized
Provided in one of the following formats:
.pkg
.dmg
.app
Use the .app binary that was compressed in the .zip file for notarization.
.zip is not supported in staple commands.
To staple the ticket created for the Notarization to the app:
smctl-mac-x64 notarization stapler <notarization ID or submission ID> -v --input <file_to_be_stapled>
Command sample:
smctl-mac-x64 notarization stapler 5cb03d00-8ab1-4fdc-bb0a-f4167dc01f03 -v --input /Users/john.doe/Documents/testing/example.dylib.dmg
Command output:
Processing: /Users/john.doe/Documents/testing/example.dylib.dmg Properties are { NSURLIsDirectoryKey = 0; NSURLIsPackageKey = 0; NSURLIsSymbolicLinkKey = 0; NSURLLocalizedTypeDescriptionKey = "Disk Image"; NSURLTypeIdentifierKey = "com.apple.disk-image-udif"; "_NSURLIsApplicationKey" = 0; } Codesign offset 0x4675f8 length: 1702 Stored Codesign length: 1702 number of blobs: 1 Total Length: 1702 Found blobs: 1 Signing information is { cdhashes = ( {length = 20, bytes = 0x5fa62fc5f5bec1f2b1464adc0d203393c0994cef} ); "cdhashes-full" = { 2 = {length = 32, bytes = 0x5fa62fc5 f5bec1f2 b1464adc 0d203393 ... d2b1af9b b513d485 }; }; cms = {length = 0, bytes = 0x}; "digest-algorithm" = 2; "digest-algorithms" = ( 2 ); flags = 2; format = "disk image"; identifier = ADHOC; "main-executable" = "file:///Users/john.doe/Documents/testing/example.dylib.dmg"; source = "explicit detached"; unique = {length = 20, bytes = 0x5fa62fc5f5bec1f2b1464adc0d203393c0994cef}; } JSON Data is { records = ( { recordName = "2/2/5fa62fc5f5bec1f2b1464adc0d203393c0994cef"; } ); } Headers: { "Content-Type" = "application/json"; } Domain is api.apple-cloudkit.com Response is <NSHTTPURLResponse: 0x600003f98000> { 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, 17 Apr 2023 06:38:32 GMT" ); Server = ( "AppleHttpServer/3faf4ee9434b" ); "Strict-Transport-Security" = ( "max-age=31536000; includeSubDomains;" ); "Transfer-Encoding" = ( Identity ); Via = ( "xrail:st53p00ic-qujn13071302.me.com:8301:22R975:grp60,631194250daa17e24277dea86cf30319:6b81ca964848d4a99a95191d693d1b6c:inbom2" ); "X-Apple-CloudKit-Version" = ( "1.0" ); "X-Apple-Edge-Response-Time" = ( 202 ); "X-Apple-Request-UUID" = ( "4dccde07-bd07-43e8-bc0c-05730d18e7de" ); "X-Responding-Instance" = ( "ckdatabasews:16305401:st42p63ic-ztfb05112201:8807:2313B296:bbd264c3ef7e69b6ed64b5c2f5a1ba0167ac99d8" ); "access-control-expose-headers" = ( "X-Apple-Request-UUID,X-Responding-Instance,Via" ); "x-apple-user-partition" = ( 63 ); } } Size of data is 2845 JSON Response is: { records = ( { created = { deviceID = 2; timestamp = 1680684243226; userRecordName = "_b133e60953755a92966d7ca08d9c731a"; }; deleted = 0; fields = { signedTicket = { type = BYTES; value = "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"; }; }; modified = { deviceID = 2; timestamp = 1681713272266; userRecordName = "_b133e60953755a92966d7ca08d9c731a"; }; pluginFields = { }; recordChangeTag = lg3g05rh; recordName = "2/2/5fa62fc5f5bec1f2b1464adc0d203393c0994cef"; recordType = DeveloperIDTicket; } ); } Downloaded ticket has been stored at file:///var/folders/x1/_4323gz167n633s877chh3_c0000gq/T/4dccde07-bd07-43e8-bc0c-05730d18e7de.ticket. Attempting to attach a new ticket to example.dylib.dmg. Let's see how that works out. Cloned /Users/john.doe/Documents/testing/example.dylib.dmg to /var/folders/x1/_4323gz167n633s877chh3_c0000gq/T/TemporaryItems/NSIRD_stapler_AqeR1S/example.dylib.dmg Adding 1 blobs to superblob. What about Blob? Length of new ticket blob is 1682 A copy of the new disk image blobs and headers has been saved to /var/folders/x1/_4323gz167n633s877chh3_c0000gq/T/C81805ED-D342-4A40-A289-EB5B6DAE3FF4-94768-00007880DD322E37.dmgData. Enjoy. Processing: /Users/john.doe/Documents/testing/example.dylib.dmg Properties are { NSURLIsDirectoryKey = 0; NSURLIsPackageKey = 0; NSURLIsSymbolicLinkKey = 0; NSURLLocalizedTypeDescriptionKey = "Disk Image"; NSURLTypeIdentifierKey = "com.apple.disk-image-udif"; "_NSURLIsApplicationKey" = 0; } Codesign offset 0x4675f8 length: 1702 Stored Codesign length: 1702 number of blobs: 1 Total Length: 1702 Found blobs: 1 Signing information is { cdhashes = ( {length = 20, bytes = 0x5fa62fc5f5bec1f2b1464adc0d203393c0994cef} ); "cdhashes-full" = { 2 = {length = 32, bytes = 0x5fa62fc5 f5bec1f2 b1464adc 0d203393 ... d2b1af9b b513d485 }; }; cms = {length = 0, bytes = 0x}; "digest-algorithm" = 2; "digest-algorithms" = ( 2 ); flags = 2; format = "disk image"; identifier = ADHOC; "main-executable" = "file:///Users/john.doe/Documents/testing/example.dylib.dmg"; source = "explicit detached"; unique = {length = 20, bytes = 0x5fa62fc5f5bec1f2b1464adc0d203393c0994cef}; } The staple and validate action worked! stapleCommand command for file /Users/john.doe/Documents/testing/example.dylib.dmg was SUCCESSFUL a7abfd6f-6367-443e-96a6-ab7dff751447
List notarizations
To list notarizations, run:
smctl-mac-x64 notarization ls
Command output:
ID SUBMISSION ID CREATED ON ACCOUNT ID SIGNATURE ID a7abfd6f-6367-443e-96a6-ab7dff751447 5cb03d00-8ab1-4fdc-bb0a-f4167dc01f03 2023-04-17 06:34:20 +0000 UTC f28bd2a7-0183-4311-b40b-826ea4b1b3e4 fd8c9be9-d548-48e5-961b-9f3e1361c356 08a7c877-9e11-46d7-8936-a76398f44313 2023-04-17 06:35:13 +0000 UTC f28bd2a7-0183-4311-b40b-826ea4b1b3e4 e286e9c7-76b2-45ad-9c04-ad7ae171b5d7 2023-04-17 06:34:04 +0000 UTC f28bd2a7-0183-4311-b40b-826ea4b1b3e4 89ef3f9b-6528-4ff1-a7a0-227235ed5e15 2023-04-17 06:33:34 +0000 UTC f28bd2a7-0183-4311-b40b-826ea4b1b3e4 217f182c-6e08-4cc3-bb2f-8717dc0512a5 71daf9d8-403d-4884-9647-073c2c2d3de9 2023-04-17 06:26:53 +0000 UTC f28bd2a7-0183-4311-b40b-826ea4b1b3e4 8c60cd99-0d13-4c0e-9818-82251ae584fe fce8f59e-c1f3-4341-92ed-6014a0cb4ec4 2023-04-17 06:12:29 +0000 UTC f28bd2a7-0183-4311-b40b-826ea4b1b3e4 41fa58ed-c22b-450e-91f8-55a1568d4dc2 2023-04-17 06:24:22 +0000 UTC f28bd2a7-0183-4311-b40b-826ea4b1b3e4 e981f52c-0857-435c-afcf-228138fd05c2 2023-04-17 06:23:45 +0000 UTC f28bd2a7-0183-4311-b40b-826ea4b1b3e4 ca9c10ab-b2e5-48fc-abee-4b018a0b6779 2023-04-17 06:13:14 +0000 UTC f28bd2a7-0183-4311-b40b-826ea4b1b3e4 41fcf167-2ca7-4c84-aff1-eb664c5c7150 2f623367-7cba-4269-b391-e433f83d4e6c 2023-04-17 06:09:41 +0000 UTC f28bd2a7-0183-4311-b40b-826ea4b1b3e4 b553418a-f77e-4fb2-81a2-8ddab656b3cc 35581022-e5a3-4361-9418-b2e1995f5cca 2023-04-17 06:08:29 +0000 UTC f28bd2a7-0183-4311-b40b-826ea4b1b3e4
Describe notarizations
To describe notarizations:
smctl-mac-x64 notarization describe <notarization ID>
Command sample:
smctl-mac-x64 notarization describe 5cb03d00-8ab1-4fdc-bb0a-f4167dc01f03
Command output:
ID: a7abfd6f-6367-443e-96a6-ab7dff751447 SUBMISSION ID: 5cb03d00-8ab1-4fdc-bb0a-f4167dc01f03 SIGNATUREID: CREATED ON:2023-04-17 06:34:20 +0000 UTC CREATED BY:stm user MODIFIED ON:2023-04-17 06:38:32 +0000 UTC MODIFIED BY:stm user ACCOUNT ID:f28bd2a7-0183-4311-b40b-826ea4b1b3e4 LOG: Tool Used: stapler Timestamp:2023-04-17 06:38:32.401508 +0000 UTC log: Processing: /Users/john.doe/Documents/testing/example.dylib.dmg Properties are { NSURLIsDirectoryKey = 0; NSURLIsPackageKey = 0; NSURLIsSymbolicLinkKey = 0; NSURLLocalizedTypeDescriptionKey = "Disk Image"; NSURLTypeIdentifierKey = "com.apple.disk-image-udif"; "_NSURLIsApplicationKey" = 0; } Codesign offset 0x4675f8 length: 1702 Stored Codesign length: 1702 number of blobs: 1 Total Length: 1702 Found blobs: 1 Signing information is { cdhashes = ( {length = 20, bytes = 0x5fa62fc5f5bec1f2b1464adc0d203393c0994cef} ); "cdhashes-full" = { 2 = {length = 32, bytes = 0x5fa62fc5 f5bec1f2 b1464adc 0d203393 ... d2b1af9b b513d485 }; }; cms = {length = 0, bytes = 0x}; "digest-algorithm" = 2; "digest-algorithms" = ( 2 ); flags = 2; format = "disk image"; identifier = ADHOC; "main-executable" = "file:///Users/John.Doe/Documents/testing/example.dylib.dmg"; source = "explicit detached"; unique = {length = 20, bytes = 0x5fa62fc5f5bec1f2b1464adc0d203393c0994cef}; } JSON Data is { records = ( { recordName = "2/2/5fa62fc5f5bec1f2b1464adc0d203393c0994cef"; } ); } Headers: { "Content-Type" = "application/json"; } Domain is api.apple-cloudkit.com Response is <NSHTTPURLResponse: 0x600003f98000> { 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, 17 Apr 2023 06:38:32 GMT" ); Server = ( "AppleHttpServer/3faf4ee9434b" ); "Strict-Transport-Security" = ( "max-age=31536000; includeSubDomains;" ); "Transfer-Encoding" = ( Identity ); Via = ( "xrail:st53p00ic-qujn13071302.me.com:8301:22R975:grp60,631194250daa17e24277dea86cf30319:6b81ca964848d4a99a95191d693d1b6c:inbom2" ); "X-Apple-CloudKit-Version" = ( "1.0" ); "X-Apple-Edge-Response-Time" = ( 202 ); "X-Apple-Request-UUID" = ( "4dccde07-bd07-43e8-bc0c-05730d18e7de" ); "X-Responding-Instance" = ( "ckdatabasews:16305401:st42p63ic-ztfb05112201:8807:2313B296:bbd264c3ef7e69b6ed64b5c2f5a1ba0167ac99d8" ); "access-control-expose-headers" = ( "X-Apple-Request-UUID,X-Responding-Instance,Via" ); "x-apple-user-partition" = ( 63 ); } } Size of data is 2845 JSON Response is: { records = ( { created = { deviceID = 2; timestamp = 1680684243226; userRecordName = "_b133e60953755a92966d7ca08d9c731a"; }; deleted = 0; fields = { signedTicket = { type = BYTES; value = "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"; }; }; modified = { deviceID = 2; timestamp = 1681713272266; userRecordName = "_b133e60953755a92966d7ca08d9c731a"; }; pluginFields = { }; recordChangeTag = lg3g05rh; recordName = "2/2/5fa62fc5f5bec1f2b1464adc0d203393c0994cef"; recordType = DeveloperIDTicket; } ); } Downloaded ticket has been stored at file:///var/folders/x1/_4323gz167n633s877chh3_c0000gq/T/4dccde07-bd07-43e8-bc0c-05730d18e7de.ticket. Attempting to attach a new ticket to example.dylib.dmg. Let's see how that works out. Cloned /Users/john.doe/Documents/testing/example.dylib.dmg to /var/folders/x1/_4323gz167n633s877chh3_c0000gq/T/TemporaryItems/NSIRD_stapler_AqeR1S/example.dylib.dmg Adding 1 blobs to superblob. What about Blob? Length of new ticket blob is 1682 A copy of the new disk image blobs and headers has been saved to /var/folders/x1/_4323gz167n633s877chh3_c0000gq/T/C81805ED-D342-4A40-A289-EB5B6DAE3FF4-94768-00007880DD322E37.dmgData. Enjoy. Processing: /Users/john.doe/Documents/testing/example.dylib.dmg Properties are { NSURLIsDirectoryKey = 0; NSURLIsPackageKey = 0; NSURLIsSymbolicLinkKey = 0; NSURLLocalizedTypeDescriptionKey = "Disk Image"; NSURLTypeIdentifierKey = "com.apple.disk-image-udif"; "_NSURLIsApplicationKey" = 0; } Codesign offset 0x4675f8 length: 1702 Stored Codesign length: 1702 number of blobs: 1 Total Length: 1702 Found blobs: 1 Signing information is { cdhashes = ( {length = 20, bytes = 0x5fa62fc5f5bec1f2b1464adc0d203393c0994cef} ); "cdhashes-full" = { 2 = {length = 32, bytes = 0x5fa62fc5 f5bec1f2 b1464adc 0d203393 ... d2b1af9b b513d485 }; }; cms = {length = 0, bytes = 0x}; "digest-algorithm" = 2; "digest-algorithms" = ( 2 ); flags = 2; format = "disk image"; identifier = ADHOC; "main-executable" = "file:///Users/john.doe/Documents/testing/example.dylib.dmg"; source = "explicit detached"; unique = {length = 20, bytes = 0x5fa62fc5f5bec1f2b1464adc0d203393c0994cef}; } The staple and validate action worked! Tool Used: notarytool Timestamp:2023-04-17 06:37:27.506724 +0000 UTC log: { "logFormatVersion": 1, "jobId": "5cb03d00-8ab1-4fdc-bb0a-f4167dc01f03", "status": "Accepted", "statusSummary": "Ready for distribution", "statusCode": 0, "archiveFilename": "example.dylib.dmg", "uploadDate": "2023-04-17T06:34:20.469Z", "sha256": "40c81b1fe9528d994e56e153833896302d4d9398a6b0a3f3f5518e8b86393db6", "ticketContents": [ { "path": "example.dylib.dmg", "digestAlgorithm": "SHA-256", "cdhash": "5fa62fc5f5bec1f2b1464adc0d203393c0994cef" }, { "path": "example.dylib.dmg/example.dylib", "digestAlgorithm": "SHA-256", "cdhash": "76e7cbde3fb5434d015a22b4eccdea567e44a25b", "arch": "x86_64" } ], "issues": null } Tool Used: notarytool Timestamp:2023-04-17 06:36:34.874059 +0000 UTC log: {"status":"Accepted","id":"5cb03d00-8ab1-4fdc-bb0a-f4167dc01f03","createdDate":"2023-04-17T06:34:17.574Z","message":"Successfully received submission info","name":"example.dylib.dmg"} Tool Used: notarytool Timestamp:2023-04-17 06:34:20.706515 +0000 UTC log: {"path":"\/Users\/john.doe\/Documents\/testing\/example.dylib.dmg","id":"5cb03d00-8ab1-4fdc-bb0a-f4167dc01f03","message":"Successfully uploaded file"}
Verify notarization
To verify the stapler command, use the command:
smctl-mac-x64 notarization stapler verify -v --input <path to notarized path>
Command sample:
smctl-mac-x64 notarization stapler verify -v --input /Users/john.doe/Documents/testing/DigiCert\ example.app
Command output:
Processing: /Users/john.doe/Documents/testing/example.app Properties are { NSURLIsDirectoryKey = 1; NSURLIsPackageKey = 1; NSURLIsSymbolicLinkKey = 0; NSURLLocalizedTypeDescriptionKey = Application; NSURLTypeIdentifierKey = "com.apple.application-bundle"; "_NSURLIsApplicationKey" = 1; } Props are { cdhash = {length = 20, bytes = 0xb6073a31b4665e3e73a16f59d9ddfbc4e16912c6}; digestAlgorithm = 2; flags = 65536; secureTimestamp = "2023-03-09 14:25:26 +0000"; signingId = DigiCert; teamId = DESP6SPB3R; } JSON Data is { records = ( { recordName = "2/2/b6073a31b4665e3e73a16f59d9ddfbc4e16912c6"; } ); } Headers: { "Content-Type" = "application/json"; } Domain is api.apple-cloudkit.com Response is <NSHTTPURLResponse: 0x600002fbc0c0> { 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 = ( "Tue, 18 Apr 2023 05:46:40 GMT" ); Server = ( "AppleHttpServer/3faf4ee9434b" ); "Strict-Transport-Security" = ( "max-age=31536000; includeSubDomains;" ); "Transfer-Encoding" = ( Identity ); Via = ( "xrail:st53p00ic-qujn12061102.me.com:8301:22R975:grp60,631194250daa17e24277dea86cf30319:52127579245e6c50c59cfb57df69ab68:nlhfd1" ); "X-Apple-CloudKit-Version" = ( "1.0" ); "X-Apple-Edge-Response-Time" = ( 98 ); "X-Apple-Request-UUID" = ( "a2d569cd-58fc-4420-829d-988d54ea3504" ); "X-Responding-Instance" = ( "ckdatabasews:16308601:st42p63ic-ztfb18191901:8807:2313B296:bbd264c3ef7e69b6ed64b5c2f5a1ba0167ac99d8" ); "access-control-expose-headers" = ( "X-Apple-Request-UUID,X-Responding-Instance,Via" ); "x-apple-user-partition" = ( 63 ); } } Size of data is 2957 JSON Response is: { records = ( { created = { deviceID = 2; timestamp = 1678372170142; userRecordName = "_b133e60953755a92966d7ca08d9c731a"; }; deleted = 0; fields = { signedTicket = { type = BYTES; value = "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"; }; }; modified = { deviceID = 2; timestamp = 1681796391198; userRecordName = "_b133e60953755a92966d7ca08d9c731a"; }; pluginFields = { }; recordChangeTag = lf17geql; recordName = "2/2/b6073a31b4665e3e73a16f59d9ddfbc4e16912c6"; recordType = DeveloperIDTicket; } ); } Downloaded ticket has been stored at file:///var/folders/x1/_4323gz167n633s877chh3_c0000gq/T/a2d569cd-58fc-4420-829d-988d54ea3504.ticket. The validate action worked!verifyStaplerCommand command for file /Users/john.doe/Documents/testing/example.app was SUCCESSFUL