Overview
macOS notarization is a security process required by Apple for all software distributed outside the Mac App Store. Starting with macOS 10.15 (Catalina), all software must be notarized to run without warnings.Notarization is automatic in CI/CD when credentials are configured. This guide covers setup and troubleshooting.
Why Notarization is Required
Without notarization, users see this warning when opening your app:“MQTT Explorer.app” cannot be opened because the developer cannot be verified.Notarized apps:
- Run without security warnings
- Meet Apple’s security requirements
- Pass Gatekeeper validation
- Can be distributed via direct download or DMG
Prerequisites
Apple Developer Account
Enroll in the Apple Developer Program:
- Individual or Organization account
- Active membership ($99 USD/year)
Developer ID Certificate
Install Developer ID Application certificate:
- Log in to Apple Developer
- Navigate to Certificates, IDs & Profiles
- Create “Developer ID Application” certificate
- Download and install in Keychain Access
Setup for GitHub Actions
1. Create App-Specific Password
Generate password
- Sign in to appleid.apple.com
- Navigate to Sign-In and Security
- Under App-Specific Passwords, click Generate an app-specific password
- Enter a descriptive name:
MQTT Explorer Notarization - Copy the generated password (format:
xxxx-xxxx-xxxx-xxxx)
2. Find Your Team ID
Locate Team ID
- Sign in to developer.apple.com/account
- Navigate to Membership Details
- Copy your Team ID (10-character alphanumeric string)
A1B2C3D4E53. Configure GitHub Secrets
Add three secrets to your GitHub repository:Navigate to repository settings
- Go to your repository on GitHub
- Click Settings → Secrets and variables → Actions
- Click New repository secret
Add APPLE_ID
Name:
APPLE_IDValue: Your Apple ID email (e.g., [email protected])Add APPLE_APP_SPECIFIC_PASSWORD
Name:
APPLE_APP_SPECIFIC_PASSWORDValue: The app-specific password from step 1 (e.g., xxxx-xxxx-xxxx-xxxx)How Notarization Works
Build Configuration
Notarization is configured inpackage.json:
package.json
hardenedRuntime: true- Enables hardened runtime (required for notarization)gatekeeperAssess: false- Skips Gatekeeper assessment during buildafterSign- Runs notarization script after code signing
Notarization Script
Thescripts/notarize.ts script handles the notarization process:
scripts/notarize.ts
Process Flow
Submit to Apple
The notarization script uploads the app to Apple’s servers:Apple scans for malware and validates code signing.
Staple Ticket
After approval, the notarization ticket is stapled to the app:This embeds the notarization ticket so users can open the app offline.
Notarization typically takes 1-5 minutes. The
--wait flag blocks until Apple’s servers respond.Entitlements
Entitlements define the permissions your app requires.DMG Build Entitlements
Parent App:res/entitlements.mac.plist
res/entitlements.mac.inherit.plist
Mac App Store Entitlements
MAS Build:res/entitlements.mas.plist
Entitlement Selection
Thepackage.ts script selects entitlements based on build type:
package.ts
Local Testing
Test notarization locally before committing to CI/CD:CI/CD Integration
Notarization runs automatically in.github/workflows/platform-builds.yml:
.github/workflows/platform-builds.yml
- Builds the app with electron-builder
- Signs with Developer ID certificate (auto-detected from Keychain)
- Runs
scripts/notarize.tsafter signing - Uploads notarized DMG to GitHub Releases
GitHub-hosted macOS runners include Xcode and can access certificates in the Keychain.
Checking Notarization Status
Check Notarization History
View recent notarization submissions:Check Specific Submission
Get detailed logs for a submission:Verify Installed App
Check if an installed app is notarized:Troubleshooting
Notarization Rejected
Notarization Rejected
Symptom: Notarization fails with “Invalid” statusCheck logs:Common issues:
- Missing hardened runtime: Set
hardenedRuntime: trueinpackage.json - Invalid entitlements: Verify plist files are well-formed XML
- Unsigned frameworks: Ensure all dependencies are code-signed
- Malware detected: Scan your code for suspicious patterns
Authentication Failed
Authentication Failed
Symptom: Solutions:
Error: Unable to authenticateVerify credentials:- Regenerate app-specific password at appleid.apple.com
- Update GitHub secrets with new password
- Verify Team ID matches your developer account
Certificate Not Found
Certificate Not Found
Symptom: Solutions:
No identity found for signingCheck certificates:- Install Developer ID Application certificate
- Import certificate to Keychain Access
- Verify certificate is not expired
- On CI: Ensure certificate is uploaded to runner secrets
Timeout During Notarization
Timeout During Notarization
Symptom: Notarization hangs or times outApple’s servers are slow: This is normal. Notarization can take 1-10 minutes.Workaround:
- Increase timeout in GitHub Actions (default: 60 minutes)
- Run
xcrun notarytool wait <submission-id>to resume
Gatekeeper Blocks App
Gatekeeper Blocks App
Symptom: User sees “cannot be opened because the developer cannot be verified”Verify notarization:Solutions:
- Re-notarize the app
- Ensure ticket is stapled:
stapler validate app.app - User workaround: Right-click app, select “Open”, click “Open”
Security Best Practices
Protect Credentials
- Never commit Apple credentials to git
- Use app-specific passwords, not main password
- Rotate passwords periodically
- Limit GitHub secret access to admins
Validate Before Release
- Test notarized builds locally
- Verify app launches without warnings
- Check Gatekeeper status with
spctl - Install and test on clean macOS VM
Monitor Apple's Requirements
- Apple updates notarization requirements annually
- Subscribe to Apple Developer News
- Update Xcode and notarytool regularly
Keep Certificates Valid
- Developer ID certificates expire in 5 years
- Renew before expiration to avoid interruptions
- Update GitHub CI/CD with renewed certificate
Mac App Store Distribution
For Mac App Store submission (separate from notarization):Submit for review
Complete submission in App Store Connect:
- Add screenshots
- Write app description
- Set pricing
- Submit for review
Mac App Store apps undergo a separate review process in addition to notarization.
References
- Apple Notarization Documentation
- electron-builder Code Signing
- @electron/notarize on GitHub
- notarytool Command Reference
Next Steps
Releases
Automate notarized releases with semantic versioning
Packaging
Learn about packaging for all platforms