#451: mac gatekeeper quarantine removal#1794
#451: mac gatekeeper quarantine removal#1794shodiBoy1 wants to merge 18 commits intodevonfw:mainfrom
Conversation
…ntine-removal' into feature/451-mac-gatekeeper-quarantine-removal
Coverage Report for CI Build 24485428778Coverage increased (+0.02%) to 70.474%Details
Uncovered ChangesNo uncovered changes found. Coverage Regressions86 previously-covered lines in 3 files lost coverage.
Coverage Stats💛 - Coveralls |
hohwille
left a comment
There was a problem hiding this comment.
@shodiBoy1 thanks for your PR. Great that you are working on this nasty problem that is currently blocking Mac users and renders the UX of IDEasy on Mac void. 👍
Currently, I do not see the difference in the xattr compared to PR #453. Can you explain why this should fix the problem now? Have you tested this approach on MacOS and it worked for unsigned apps like e.g. IntelliJ?
FYI: Did you also see this comment? #451 (comment)
When we remove the quarantine attribute, MacOS protected the app directory and we cannot make any modifications to it after that. This IMHO implies that we cannot keep the current solution with the .ide.software.version file that we simply copy to the linkDir as a workaround. Maybe it could work if we do that before we remove the quarantine attribute?
Further, in PR #453 @jan-vcapgemini made a review comment that this xattr execution should be moved to MacOsHelper what makes sense to me and should be followed.
| postExtractHook(postExtractHook, properInstallDir); | ||
| move(properInstallDir, targetDir); | ||
| delete(tmpDir); | ||
| removeQuarantineAttribute(targetDir); |
There was a problem hiding this comment.
This should only happen for an application. The extract function is generic and can also be used to extract a ZIP file with pure data or config that is not an application. Please note that the executed xattr command will typically trigger a popup with password request so this should only appear for applications (ideally only if they are not signed).
Please check PR #453 where this was already done in the right place.
| ProcessResult result = this.context.newProcess().executable("xattr") | ||
| .addArgs("-r", "-d", "com.apple.quarantine", path).run(ProcessMode.DEFAULT_SILENT); |
There was a problem hiding this comment.
This looks exactly like what I did in PR #453. However, I tested my solution and it did not work.
Am I missing something or why should it work now?
|
previous fix was wrong just doing xattr -r -d com.apple.quarantine isn't enough on macOS 15.1+ with Apple Silicon. Unsigned apps still get blocked even without the quarantine attribute. new fix xattr -cr to clear all extended attributes, then codesign --force --deep --sign - to ad-hoc sign the .app bundle. The codesign part is what actually makes it work. I skip signing if codesign -v passes so we don't break already notarized apps like Eclipse. Moved the logic into MacOsHelper.removeQuarantineAttribute() and it's called from LocalToolCommandlet.installTool() now, not from extract. .ide.software.version stays at rootDir can't write inside the .app after codesigning or you get "Operation not permitted". Version file is written before signing so no issue there. Tested with IntelliJ CE and Android Studio on M1 Pro, works fine. |
hohwille
left a comment
There was a problem hiding this comment.
@shodiBoy1 thanks for your update. Now this looks way more promising. 👍
However, there are still things to clarify before we can merge.
| } | ||
| } | ||
| } catch (Exception e) { | ||
| LOG.trace("Codesign not available for {}: {}", appDir, e.getMessage()); |
There was a problem hiding this comment.
same here? Raise to info or warn, always include the exception itself so stracktrace can be seen.
BTW: If I am not mistaken, we only print stacktraces if log-level is error or otherwise if debug or trace is activated.
There was a problem hiding this comment.
yep, changed both to LOG.warn with the exception included so it shows the exception info at warn level and full stacktrace when running in debug mode.
| if (linkDir != rootDir) { | ||
| assert (!linkDir.equals(rootDir)); | ||
| Path toolVersionFile = rootDir.resolve(IdeContext.FILE_SOFTWARE_VERSION); | ||
| if (Files.exists(toolVersionFile)) { | ||
| this.context.getFileAccess().copy(toolVersionFile, linkDir, FileCopyMode.COPY_FILE_OVERRIDE); | ||
| } | ||
| } |
There was a problem hiding this comment.
This might be problematic on macos, but if you remove it, you also need to fix the code to determine the tool version that you broke by just removing this code-block.
There was a problem hiding this comment.
version detection still works just a different approach. before, linkDir pointed inside the .app bundle so the symlink landed there, and the version file had to be copied from rootDir into linkDir.
in my fix linkDir == rootDir, so the symlink points to the top level directory where the version file is already written no copy needed.
also copying into the .app bundle would break after codesigning since macOS seals it. binaries are still found correctly through findBinDir() in getToolBinPath() which navigates into the .app bundle to find executables.
There was a problem hiding this comment.
@hohwille you were right, I didn't fully understand how linkDir and rootDir work together. i broke the linkDir assignment by collapsing two lines into one. I restored it so linkDir points inside the
.app bundle again. instead of copying the version file into the bundle (which would break codesigning), I changed getInstalledVersion to follow the symlink back to rootDir where the version file already lives.
Co-authored-by: Jörg Hohwiller <hohwille@users.noreply.github.com>
| * https://github.com/devonfw/IDEasy/issues/1702[#1702]: UI Buttons do not scale properly with window resize | ||
| * https://github.com/devonfw/IDEasy/issues/1751[#1751]: Add go commandlet (go-lang support) | ||
| * https://github.com/devonfw/IDEasy/issues/1732[#1732]: Add stash support for git-pull | ||
| * https://github.com/devonfw/IDEasy/issues/451[#451]: Automatically remove macOS quarantine attribute after tool extraction |
There was a problem hiding this comment.
I resolved the merge conflict.
But this line still needs to be moved up.
Maybe even to 2026.05.001 that is not yet added to the CHANGELOG.
There was a problem hiding this comment.
moved changelog entry up to 2026.04.002
Co-authored-by: Jörg Hohwiller <hohwille@users.noreply.github.com>
…ntine-removal' into feature/451-mac-gatekeeper-quarantine-removal
…n file through symlink
This PR fixes #451
Implemented changes:
On modern macOS (15.1+, Apple Silicon), just removing com.apple.quarantine didn't work - unsigned apps still showed the "is damaged" popup. Tested this on a real M1 Pro with IntelliJ CE and Android Studio.
The fix does two things after extraction:
Other changes:
Checklist for this PR
mvn clean testlocally all tests pass and build is successful#«issue-id»: «brief summary»(e.g.#921: fixed setup.bat). If no issue ID exists, title only.In Progressand assigned to you or there is no issue (might happen for very small PRs)with
internal