Skip to main content

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.

Command

Stapler commands begin with:

smctl-mac-x64 notarization stapler <notarization ID or submission ID> <flags>

Flags

Stapler commands support these flags:

Tableau 1. Flags for stapler commands

Shortcut

Flag

Description

--input string

Path to file.

-v

--verbose

Enable verbose logging for saving credentials.

-h

--help

Help for describing a scan.


Example

Description: Staple the ticket created for the Notarization to the app.

Command:

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

Output sample:

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/smpkcs11.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

Troubleshooting

For help with the describe scan command, use:

smctl-mac-x64 notarization stapler --help

Alternatively, use the abbreviated version of the command:

smctl-mac-x64 notarization stapler -h