You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Etterna is currently distributed as an unsigned app on all platforms, including macOS.
Windows throws some mildly-scary looking warnings up to users (which most people are conditioned to bypassing anyway), but macOS takes many active measures to severely limit the functionality of unsigned apps for security reasons.
At this point, many bugs exist and have been encountered by users stemming indirectly from this problem, and they will only become greater and harder/impossible to work around in the future.
App Translocation:
By default, macOS prevents apps from accessing resources relative to the app's location.
This is to prevent a class of attacks known as "dylib hijacking", wherein an attacker maliciously replaces external resources used by an app, which can potentially cause even signed intact apps to exhibit unintended malicious behavior. [1]
To fix this, recent versions of macOS do not always launch apps with a current working directory equal to where the app actually lives on disk. Instead, apps are sometimes launched from a read-only dynamically created volume under /private/var/ containing the app and any internal resources. This process is known as "App Translocation", and occurs when certain conditions are met, including the launching of an unsigned app with the com.apple.quarantine xattr set (which occurs automatically when apps are downloaded through Safari) [2][3] This breaks Etterna because we intentionally store the Songs and Saves directories relative to Etterna.app itself, instead of within ~/Library/Application\ Support like Apple intends us to.
We currently work around this in an incredibly hacky way, by explicitly checking if we are undergoing app translocation, locating the real location of Etterna.app if so, and directly removing the com.apple.quarantine xattr from our own app ourselves before then killing and relaunching Etterna. See:
std::system(fmt::format("open -n -a {}", untranslocatedURL.path.UTF8String).c_str());
// Close this instance
std::exit(0);
}
}
This workaround is bad for a number of reasons:
It is fragile, in that it relies upon the internal function SecTranslocateCreateOriginalPathForURL in the Security framework [4]
This is certainly something Apple doesn't want us doing and relies upon an internal function that could change or disappear in the future.
The roundaboutness of the way we try to do this has caused problems
Sometimes, we fail to untranslocate ourselves for whatever reason (e.g. Etterna mistakenly being launched from a read-only volume), and the way our current code responds is by repeatedly opening new Etterna instances which then kill themselves after opening others in an eternal loop: [Bug]: Fix translocation removal behavior when unexpected things occur #1174
It appears macOS Ventura/Sonoma may have once again changed how the quarantine process works -- I (bluebandit21) had a Discord DM conversation helping someone with problems they encountered with our unquarantining process; see also [5]
This might make our approach stop working, as it appears only certain trusted apps (e.g. Terminal) can interact with the protected com.apple.provenance xattr TODO: Expand this further/confirm?
Input Handling
Currently, we use a horribly outdated API for handling low-level input on macOS, as described by #1260 and other issues/discussions.
This API requires elevated permissions to be allowed for use by an app, namely the Input Monitoring permission, without which certain API calls fail with a lack-of-permissions error. (TODO: Expand, link to relevant detailed sources)
Unfortunately, the system for handling per-app permissions seems to somehow interact with whether the app is signed or not; sometimes the com.apple.quarantine xattr seems to have to be removed before it's even possible to grant Etterna permissions to Input Monitoring in the first place! (TODO: This is possibly also related to us not having a valid CFBundleID; investigate further...)
See: https://gist.github.com/bluebandit21/d34d7b0b4f9137c34c167e607db63c03
Native M-Series (Apple Silicon) Builds
To ease the transition when Apple switched from Intel's x86_64 chips to their own in-house ARM (aarch64) chips, Apple created the library Rosetta v2 which transparently and efficiently lets Apps compiled for the x86_64 architecture run on aarch64, via a JIT compilation layer. [6] This fortunately means that existing Etterna apps built for x86_64 do not encounter any more problems than we already do when trying to run on M-series machines.
However, we definitely want to get native ARM macOS builds working at some point for two main reasons:
One, we take a moderate, but not insignificant, performance hit by operating through the rosetta v2 translation layer.
Two, eventually Apple will stop support for x86_64 apps in the future, and the only way to run apps on modern Apple computers will be by compiling them targeting ARM. When Apple released Rosetta v1 for the PowerPC to Intel transition, they supported PowerPC apps from 2006 until 2011, or five years. [7]
Apple released Rosetta V2 in 2020; if we assumed the same five-year lifespan for it, we'd expect them to drop support sometime in 2025, less than two years away from the time of this issue's creation!
Why is this of potential concern w.r.t. notarization/signing? Because modern versions of macOS require any apps running natively on M-series to be signed and notarized to run!
Beginning in macOS 10.14.5, software signed with a new Developer ID certificate and all new or updated kernel extensions must be notarized to run. Beginning in macOS 10.15, all software built after June 1, 2019, and distributed with Developer ID must be notarized. However, you aren’t required to notarize software that you distribute through the Mac App Store because the App Store submission process already includes equivalent security checks. [8]
Conclusion:
We should probably actually figure out how to notarize ourselves on Etterna!!
The most straightforward route would probably be to have a single individual developer for Etterna (most likely @jameskr97 or @bluebandit21 ) pay for a personal Apple Developer license at the cost of $99/year and sign all releases intended for public distribution. [9]
This would likely have to be a manual process, or we'd have to very carefully modify the CI to make it possible for this signing to occur without leaking the personal signing information of the said developer...
Another possible way would be establishing an Organization Apple Developer account for Etterna, also at the cost of $99/year. This obviously has the relative downside that we'd have to somehow generate this money specifically for Etterna, while the "Individual random developer" route might be "free" in the sense that we might just have access a developer that already pays this cost and lets us use their signing identity at no additional cost to either us or them.
However, it is theoretically possible we could get this fee completely waived for us by applying for a non-profit fee waiver.[10]
This would require Etterna to have a legal Non-Profit status, which might be much more work than the potential benefit it provides.
The text was updated successfully, but these errors were encountered:
@jameskr97 Could I ask you to quickly double-check this hecking essay of an issue post for correctness?
I believe everything I'm saying is correct and should be well-supported by the many citations I've included inline, but always good to have a second set of eyes :)
Note: I snapshotted all of the resources I link to on archive.org, so they should be available there if Apple takes down/moves random documentation pages as they like to do :)
Introduction
Etterna is currently distributed as an unsigned app on all platforms, including macOS.
Windows throws some mildly-scary looking warnings up to users (which most people are conditioned to bypassing anyway), but macOS takes many active measures to severely limit the functionality of unsigned apps for security reasons.
At this point, many bugs exist and have been encountered by users stemming indirectly from this problem, and they will only become greater and harder/impossible to work around in the future.
App Translocation:
By default, macOS prevents apps from accessing resources relative to the app's location.
This is to prevent a class of attacks known as "dylib hijacking", wherein an attacker maliciously replaces external resources used by an app, which can potentially cause even signed intact apps to exhibit unintended malicious behavior. [1]
To fix this, recent versions of macOS do not always launch apps with a current working directory equal to where the app actually lives on disk. Instead, apps are sometimes launched from a read-only dynamically created volume under /private/var/ containing the app and any internal resources. This process is known as "App Translocation", and occurs when certain conditions are met, including the launching of an unsigned app with the com.apple.quarantine xattr set (which occurs automatically when apps are downloaded through Safari) [2] [3] This breaks Etterna because we intentionally store the
Songs
andSaves
directories relative to Etterna.app itself, instead of within~/Library/Application\ Support
like Apple intends us to.We currently work around this in an incredibly hacky way, by explicitly checking if we are undergoing app translocation, locating the real location of Etterna.app if so, and directly removing the com.apple.quarantine xattr from our own app ourselves before then killing and relaunching Etterna. See:
This workaround is bad for a number of reasons:
SecTranslocateCreateOriginalPathForURL
in theSecurity
framework [4]This is certainly something Apple doesn't want us doing and relies upon an internal function that could change or disappear in the future.
This might make our approach stop working, as it appears only certain trusted apps (e.g. Terminal) can interact with the protected com.apple.provenance xattr
TODO: Expand this further/confirm?
Input Handling
Currently, we use a horribly outdated API for handling low-level input on macOS, as described by #1260 and other issues/discussions.
This API requires elevated permissions to be allowed for use by an app, namely the
Input Monitoring
permission, without which certain API calls fail with a lack-of-permissions error. (TODO: Expand, link to relevant detailed sources)Unfortunately, the system for handling per-app permissions seems to somehow interact with whether the app is signed or not; sometimes the com.apple.quarantine xattr seems to have to be removed before it's even possible to grant Etterna permissions to Input Monitoring in the first place! (TODO: This is possibly also related to us not having a valid CFBundleID; investigate further...)
See: https://gist.github.com/bluebandit21/d34d7b0b4f9137c34c167e607db63c03
Native M-Series (Apple Silicon) Builds
To ease the transition when Apple switched from Intel's x86_64 chips to their own in-house ARM (aarch64) chips, Apple created the library Rosetta v2 which transparently and efficiently lets Apps compiled for the x86_64 architecture run on aarch64, via a JIT compilation layer. [6] This fortunately means that existing Etterna apps built for x86_64 do not encounter any more problems than we already do when trying to run on M-series machines.
However, we definitely want to get native ARM macOS builds working at some point for two main reasons:
Apple released Rosetta V2 in 2020; if we assumed the same five-year lifespan for it, we'd expect them to drop support sometime in 2025, less than two years away from the time of this issue's creation!
Why is this of potential concern w.r.t. notarization/signing? Because modern versions of macOS require any apps running natively on M-series to be signed and notarized to run!
Conclusion:
We should probably actually figure out how to notarize ourselves on Etterna!!
The most straightforward route would probably be to have a single individual developer for Etterna (most likely @jameskr97 or @bluebandit21 ) pay for a personal Apple Developer license at the cost of $99/year and sign all releases intended for public distribution. [9]
This would likely have to be a manual process, or we'd have to very carefully modify the CI to make it possible for this signing to occur without leaking the personal signing information of the said developer...
Another possible way would be establishing an Organization Apple Developer account for Etterna, also at the cost of $99/year. This obviously has the relative downside that we'd have to somehow generate this money specifically for Etterna, while the "Individual random developer" route might be "free" in the sense that we might just have access a developer that already pays this cost and lets us use their signing identity at no additional cost to either us or them.
However, it is theoretically possible we could get this fee completely waived for us by applying for a non-profit fee waiver.[10]
This would require Etterna to have a legal Non-Profit status, which might be much more work than the potential benefit it provides.
The text was updated successfully, but these errors were encountered: