mirror of
https://github.com/priyanshujain/margin-calendar.git
synced 2026-10-03 19:47:04 +00:00
The machine identifier mixed into the key was read from /etc/machine-id, which does not exist on macOS, so it was the empty string there. The salt sits next to the ciphertext and the key context is a constant in a public binary, which makes that identifier the only thing standing between a copied home directory and a readable refresh token. Empty is not a neutral contribution of no entropy, it is the absence of the binding: until now a home directory lifted off a Mac decrypted anywhere. The file has claimed otherwise since it was written. macOS now reads IOPlatformUUID from ioreg, a stock binary called by absolute path because an app launched from Finder inherits a minimal environment. The result is cached, since a process spawn is real money when key() runs on every load and every store. A failure yields an empty id and a working key rather than an error, because refusing here would lock a user out of a token that is perfectly good. iOS and Android stay empty deliberately. The sandbox is the real boundary there, and every identifier those platforms offer is reset by a reinstall, which would strand a token that was never in any danger. No migration, and that is a decision rather than an oversight. Nothing has been released, so the only install this can orphan is a development machine, and doing it now costs one reconnect instead of costing every Mac user one later. For the same reason the keychain-fallback.* paths are gone. They migrated nobody, and they were subtly wrong anyway: they carried the old salt across under the new name while deriving with the new key context, which silently produced a token that could not be opened. A migration that looks like it works and does not is worse than no migration. key() also no longer treats every failure to read the salt as absence. A missing file and a file too short to be a salt both take a fresh one, since neither has anything left to lose, but a salt that exists and will not read is now an error. Writing over it turned one transient read failure into the permanent loss of every stored token.