{"id":28667966,"url":"https://github.com/ilastik/app-pass","last_synced_at":"2026-03-04T08:31:56.978Z","repository":{"id":287933228,"uuid":"956600733","full_name":"ilastik/app-pass","owner":"ilastik","description":"Fix common issues in Mach-O binaries for notarization","archived":false,"fork":false,"pushed_at":"2026-02-24T20:09:35.000Z","size":114,"stargazers_count":3,"open_issues_count":2,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-02-25T00:27:57.177Z","etag":null,"topics":["app-bundle","app-bundles","apple","codesigning","gatekeeper","mach-o","macos","macosx","notarization"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ilastik.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-03-28T14:30:05.000Z","updated_at":"2026-02-24T20:08:44.000Z","dependencies_parsed_at":"2025-04-14T18:40:41.897Z","dependency_job_id":"53250bc4-50ca-441f-80f0-e029ab820c5e","html_url":"https://github.com/ilastik/app-pass","commit_stats":null,"previous_names":["ilastik/app-pass"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/ilastik/app-pass","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ilastik%2Fapp-pass","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ilastik%2Fapp-pass/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ilastik%2Fapp-pass/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ilastik%2Fapp-pass/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ilastik","download_url":"https://codeload.github.com/ilastik/app-pass/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ilastik%2Fapp-pass/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30076863,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-04T08:01:56.766Z","status":"ssl_error","status_checked_at":"2026-03-04T08:00:42.919Z","response_time":59,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["app-bundle","app-bundles","apple","codesigning","gatekeeper","mach-o","macos","macosx","notarization"],"created_at":"2025-06-13T17:00:41.633Z","updated_at":"2026-03-04T08:31:56.943Z","avatar_url":"https://github.com/ilastik.png","language":"Python","readme":"# app-pass\n\n[![main](https://github.com/ilastik/app-pass/actions/workflows/main.yaml/badge.svg)](https://github.com/ilastik/app-pass/actions/workflows/main.yaml)\n[![Anaconda-Server Badge](https://anaconda.org/conda-forge/app-pass/badges/version.svg)](https://anaconda.org/conda-forge/app-pass)\n\nTool to ensure an `.app` bundle pass the Gatekeeper on MacOS.\nOriginally to sign the bundle for [ilastik](https://ilastik.org).\n\nPrerequisite: You have built your app, and it runs on your own machine ;).\nProblem: You try to sign/notarize but get back many errors and are unsure how to resolve them.\n\n### Before you consider using `app-pass`, you might get away without it by:\n\n#### Doing everything via XCODE** :)\n\n#### Your app is Python-based\n * using [constructor](https://github.com/conda/constructor) if your stack is conda-based. Constructor does ad-hoc signing on install.\n * using something like [briefcase](https://github.com/beeware/briefcase).\n * [encrust](https://github.com/glyph/Encrust) seems also to work.\n * [jaunch](https://github.com/apposed/jaunch).\n\n#### Your app is Java-based\n * Consider using [jaunch](https://github.com/apposed/jaunch), which powers Fiji.\n\nIn any case, there are many reasons you can't use one of these alternatives and are left with a working .app that you can not sign.\n`app-pass` can help you no matter how you generated the app in the first place.\n\nTested so far with conda-based python apps, and java apps.\n\n`app-pass` can perform various fixes on binaries, and sign `.app` bundles.\nDoes not require using a specific way to build your `.app` bundle.\nDoes not require `.app` being written in a specific language, or framework.\n\nWe understand that making changes to the binary that you are distributing should be as transparent as possible.\nFor this, you can generate an `.sh` file that uses only apple dev tools to manipulate your `.app`.\nAny `app-pass` command invoked with `--dry-run` will not make any changes to your app.\n\n## Installation\n\nYou can find the package on pypi and conda:\n\n```\npip install app-pass\n```\n\nor\n\n```\nconda install -c conda-forge app-pass\n```\n\n## Fix/Sign/Notarize workflow\n\nIn general the workflow is roughly in these stages:\n\n1) You generate your `.app` bundle.\n2) The binaries in your app bundle are fixed, and\n3) signed.\n4) The bundle is sent to notarization with apple.\n5) `.app` is stapled and compressed again for distribution.\n6) Optional, if you have a `.dmg` installer, you rebuild it with the signed app and notarize it as well. \n\n`app-pass` helps you with steps 2, 3 and 4.\n\nFor the process of acquiring the required signing certificate and app password, please see the [jaunch documentation](https://github.com/apposed/jaunch/blob/main/doc/MACOS.md#how-to-sign-your-applications-jaunch-launcher).\n\n\n## Complete usage example\n\nSo far we've been working with the following `entitlements.plist`:\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\u003c!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"\u003e\n\u003cplist version=\"1.0\"\u003e\n\u003cdict\u003e\n    \u003ckey\u003ecom.apple.security.cs.allow-unsigned-executable-memory\u003c/key\u003e\n    \u003ctrue/\u003e\n    \u003ckey\u003ecom.apple.security.cs.allow-jit\u003c/key\u003e\n    \u003ctrue/\u003e\n\u003c/dict\u003e\n\u003c/plist\u003e\n```\n\nAn example how we would sign our ilastik .app bundle:\n\n```bash\n# unzip unsigned app bundle after build\nditto -x -k ~/Downloads/ilastik-1.4.1rc3-arm64-OSX-unsigned.zip .\n# this creates the bundle folder ilastik-1.4.1rc3-arm64-OSX.app that we will be\n# working with\n\n# fix and sign contents - for ilastik, we decide to remove rpaths that point\n# outside the bundle so we add --rc-path-delete\napp-pass fixsign -vv \\\n    --sh-output \"ilastik-1.4.1rc3-arm64-OSX-sign.sh\" \\\n    --rc-path-delete \\\n    ilastik-1.4.1rc3-arm64-OSX.app \\\n    entitlements.plist \\\n    \"Developer ID Application: \u003cYOUR DEVELOPER APPLICATION INFO\u003e\"\n\napp-pass notarize -vv \\\n    ilastik-1.4.1rc3-arm64-OSX.app \\\n    notarytool-password \\\n    /Users/kutra/Library/Keychains/login.keychain-db \\\n    \"\u003cemail-address-of-dev-account@provider.ext\u003e\" \\\n    \u003cyour-team-id\u003e \\\n\n# finally zip again for distribution\n# --noqtn --norsrc have been added as some builds resulted in .zip\n# archives that would not expand cleanly with Archive Utility\n# (AppleDouble files expanded for symlinks in the app bundle\n# which would prevent it from passing gatekeeper.)\n/usr/bin/ditto -v --noqtn --norsrc -c -k --keepParent \\\n    ilastik-1.4.1rc3-arm64-OSX.app ilastik-1.4.1rc3-arm64-OSX.zip\n```\n\n## Sub-commands\n\n\u003cdetails\u003e\u003csummary\u003e\u003cb\u003eIf your bundle includes `.jar` files\u003c/b\u003e\u003c/summary\u003e\n\nThese need to be extracted and can have case sensitive file contents.\nPer default, the file system on the mac is _not_ case sensitive!\nWhile many developers opt to change this when they get a new machine, not everyone does...\nTo mitigate this, we recommend creating a ram-disk for temporary files:\n\n```bash\n# creates a 2GB ramdisk at mountpoint /Volumes/ramdisk\n# ram://2097152 for 1GB, ram://1048576 for .5GB\ndiskutil erasevolume hfsx 'ramdisk' `hdiutil attach -nomount ram://4194304`\n```\n\nYou need to invoke all `app-pass` commands overriding then env variable `TMPDIR`, e.g. `TMPDIR=/Volumes/ramdisk app-pass fix ...`\n\n\u003c/details\u003e\n\n\n### Check\n\n```bash\n# check if app would likely pass notarization and later gatekeeper\napp-pass check \u003cpath_to_app_bundle.app\u003e\n```\n\n### Fix\n\n```bash\napp-pass fix -vv --sh-output debug.sh \u003cpath_to_app_bundle.app\u003e\n```\n\n### Sign\n\n```bash\napp-pass fix -vv --sh-output debug.sh \u003cpath_to_app_bundle.app\u003e \\\n    \u003cpath/to/entitlements.plist\u003e \\\n    \u003c\"Developer ID Application: \u003cYOUR DEVELOPER APPLICATION INFO\u003e\"\u003e\n```\n\n### Notarize\n\n```bash\napp-pass notarize -vv \u003cpath_to_app_bundle.app\u003e \\\n    \u003cyour-keychain-profile\u003e \u003cpath-to-keychain\u003e \\\n    \u003cemail-address-of-dev-account@provider.ext\u003e \u003cyour-team-id\u003e\n```\n\n### `--dry-run` and `--sh-output`\n\n`app-pass` is built to make it easy for you to audit changes to your app.\nInvoking `app-pass` with `--dry-run` and `--sh-output \u003coutput-script.sh\u003e` will not do any changes to your app.\nInstead, it will generate a shell script containing all the commands using standard Apple developer tools that would be executed to modify your app.\n\nAn exception is the `notarize` subcommand, that currently does not support generating an `.sh` file.\n\n\u003cdetails\u003e\u003csummary\u003e`notarize.sh` equivalent\u003c/summary\u003e\n\n```bash\n# pack to get ready for notarization\n/usr/bin/ditto -v -c -k --keepParent \\\n    myapp.app myapp-tosign.zip\n\n# send off to apple:\nxcrun notarytool submit \\\n    --keychain-profile \u003cyour-keychain-profile\u003e \\\n    --keychain \u003cpath-to-keychain\u003e \\\n    --apple-id  \u003cemail-address-of-dev-account@provider.ext\u003e \\\n    --team-id \u003cyour-team-id\u003e \\\n    \"myapp-tosign.zip\"\n\n# wait for notarization is complete\nxcrun notarytool wait \\\n    --keychain-profile \u003cyour-keychain-profile\u003e \\\n    --keychain \u003cpath-to-keychain\u003e \\\n    --apple-id  \u003cemail-address-of-dev-account@provider.ext\u003e \\\n    --team-id \u003cyour-team-id\u003e \\\n    \u003cnotarization-request-id\u003e\n\n# once this is done, staple:\nxcrun stapler staple myapp.app\n```\n\n\u003c/details\u003e\n\n\n## Good reading material on the topic of signing/notarizing\n\n* [Fun read on signing/notarization in general](https://blog.glyph.im/2023/03/py-mac-app-for-real.html), also the author of [encrust](https://github.com/glyph/Encrust)\n* [Good overview of signing process, how to get certificates](https://briefcase.readthedocs.io/en/stable/how-to/code-signing/macOS.html) (briefcase documentation). Also probably a good option to develop your app from the start to ease with signing/notarizing.\n* [Apple TN2206: macOS Code Signing In Depth](https://developer.apple.com/library/archive/technotes/tn2206/_index.html)\n* [Apple docs on notarizing from the terminal](https://developer.apple.com/documentation/security/customizing-the-notarization-workflow)\n\n\n## What kind of issues does this package fix?\n\nThis package mostly manipulates the load commands of your Mach-O binaries using standard Apple developer tools such as `install_name_tool`, and `vtool`.\nTo look at any of these load commands `otool -l \u003cdylib-path\u003e` is your friend.\n\n### Build versions and platform (`LC_BUILD_VERSION`)\n\nNotarization requires `platform`, `minos`, and `sdk` versions to be set.\nIn older binaries these can be partly missing.\n\nAnother requirement is that `sdk` version is newer or equal to `10.9`.\nThere is the `--force-update` flag that will at least result in a app passing notarization.\nWe're still investigating if there's any downsides to this (for executables we found that they will not run, but libraries might work).\n\n### Dynamic library search paths (`LC_RPATH`)\n\nThese paths may not point outside the `.app` folder for notarization to be successful (except for `/System/`, `/usr/`, `/Library/`).\n`app-pass` tries do something sensible if these paths are absolute but point inside the app and replaces these with something relative to `@loader_path`, or `@executable_path`.\n\nSome libraries have rpaths pointing outside the app.\nDo these even exist on your machine?\nThe ones we found so far were artifacts of the build process and wouldn't exist on our machines.\nThe option `--rc-path-delete` will delete these rpaths from libraries.\n\n### Linked dynamic libraries (`LC_LOAD_DYLIB`, `LC_REEXPORT_DYLIB`)\n\nTo pass notarization these paths may not be absolute, or point outside the app.\n`app-pass` will try to locate the libs within the .app and add a relative link.\n\n### Library ID (`LC_ID_DYLIB`)\n\nThis has to be a relative path inside the app.\nWill be fixed to `@rpath/libname` if found otherwise.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Filastik%2Fapp-pass","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Filastik%2Fapp-pass","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Filastik%2Fapp-pass/lists"}