Archive for October 7, 2024

Monday, October 7, 2024

Launching Before UserDefaults Is Available

Christian Selig (Mastodon):

It seems at some point, even though UserDefaults is intended for non-sensitive information, it started getting marked as data that needs to be encrypted and cannot be accessed until the user unlocked their device. I don’t know if it’s because Apple found developers were storing sensitive data in there even when they shouldn’t be, but the result is even if you just store something innocuous like what color scheme the user has set for your app, that theme cannot be accessed until the device is unlocked.

[…]

Again, who cares? Users have to unlock the device before launching my app, right? I thought so too! It turns out, even though Apple’s prewarming documentation states otherwise, developers have been reporting for years that that’s just wrong, and your app can effectively be fully launched at any time, including before the device is even unlocked.

Combining this with the previous UserDefaults change, you’re left with the above situation where the app is launched with crucial data just completely unavailable because the device is still locked.

[…]

If you use Live Activities at all, the cool new API that puts activities in your Dynamic Island and Lock Screen, it seems if your app has an active Live Activity and the user reboots their device, virtually 100% of the time the above situation will occur where your app is launched in the background without UserDefaults being available to it.

UserDefaults doesn’t actually report an error, and this can lead to incorrect behavior and data loss.

Christian Selig:

It’s a really rough bug, because if you sometimes can’t trust UserDefaults, it means you can read out data from it with the intent to modify it slightly before saving it back, only now you’re modifying junk data and overwriting the good data 🫤

Quinn (in 2015):

IMO the best way around this is to avoid NSUserDefaults for stuff that you rely on in code paths that can execute in the background. Instead store those settings in your own preferences file, one whose data protection you can explicitly manage[…]

NSFileProtectionCompleteUntilFirstUserAuthentication and prewarming don’t apply on the Mac, but similar problems can occur there. A common cause of support issues is that the customer has entered some data or changed a setting, and the app seems to work normally for that launch, but upon relaunch all the changes are forgotten. macOS doesn’t notify the app that the data was never saved to the .plist file, e.g. because of a file permissions problem or because the user tried to redirect the user defaults storage using a symlink.

Previously:

Update (2024-10-08): Guy English:

“Changed” may be off the mark here too—I think those security changes were done way back in iOS 7. I suspect what’s happening is that the issue is becoming more apparent due to the differing security contexts code is running under more frequently now. It makes sense to secure the Defaults. But it also makes sense to store non-sensitive defaults there… so it’s a pickle currently.

Pasi Salenius:

In addition to encrypted userdefaults being unavailable on background launches, there is something else that is not working right. I sometimes notice defaults not being available in viewDidLoad, and have received reports of that happening to my users. It usually happens after an OS update and reboot.

Christian Selig:

Yeah that’s part of the whole “full launch” business unfortunately, appDidFinishLaunching and corresponding view controllers will be fully getting built without UserDefaults being available even though the docs on prewarming state otherwise.

Dealing With Objective-C Protocol Types in Swift

Dave Rahardja:

There are two ways to refer to this protocol in Swift: using a native Swift type, or using an Objective-C Protocol object reference.

let fungibleSwiftProtocol = Fungible.self
let fungibleObjCProtocol = NSProtocolFromString("Fungible")!

These two types should be the same—after all, they refer to the same protocol—but they are not, as shown when we print out their descriptions and ObjectIdentifiers[…]

[…]

The answer is yes: there is a way to convert a Swift type that refers to an Objective-C protocol into an Objective-C Protocol reference.

[…]

fungibleSwiftProtocol as AnyObject as? Protocol

There is apparently no way to convert in the other direction.

Previously:

Xcode 16 Folders and Groups

Sarah Reichelt (Mastodon):

In Xcode 16, project files and folders are arranged differently in the Project navigator. What used to be a group is now a folder, and this simple change has some interesting effects. At first, I was against the new scheme - in fact in my SwiftUI for Mac 2024 article, I specifically recommended reverting back to the old group method. But after doing some more reading and testing, I think the answer is not so clear cut.

[…]

At a first glance, there are two differences: the order of the files & folders and the color of the folder icons. A less obvious difference is that in Xcode 15, I can drag files around to arrange them in the order I prefer. In Xcode 16, I can’t do that. I can drag files into or out of folders, but I can’t move them around at the same level.

[…]

This points out the fundamental difference between the two approaches: groups are an artificial construct that is stored in the project files. Usually, this mirrors the file and folder structure in Finder, but it doesn’t have to. When you use folders, Xcode is reading the file and folder structure directly from the Finder.

[…]

The big difference is in source control, especially if you’re working with other people. When every file addition, deletion or move also changes the project file, you have a much greater chance of getting a merge conflict.

Previously:

Meta Fined for Logging Passwords

Alexander Martin (via Hacker News):

The social media giant Meta has been fined €91 million ($101 million) for accidentally storing hundreds of millions of its users’ passwords in plaintext instead of in an encrypted format on its internal systems.

Meta first announced discovering the engineering mistake back in 2019. At the time, the company stated it would be notifying everyone whose passwords were stored without protection although it stressed the passwords were only exposed internally at Meta, and there was no evidence that any of them had been abused.

Following a five year investigation, the Irish Data Protection Commission (DPC) — which is the EU’s lead privacy authority on Meta, as the company’s European headquarters are based in Ireland — found the incident was a breach of Meta’s legal duties under the EU’s General Data Protection Regulations (GDPR).

Dan Goodin (Hacker News):

The company said that apps for connecting to various Meta-owned social networks had logged user passwords in plaintext and stored them in a database that had been searched by roughly 2,000 company engineers, who collectively queried the stash more than 9 million times.

[…]

For more than three decades, best practices across just about every industry have been to cryptographically hash passwords.

Because “only” hundreds of millions of users are affected, it sounds like they were not actually storing the passwords in the database unhashed. Rather, they were probably inappropriately logging some raw request data. So it’s not that the passwords should have been hashed but that they shouldn’t have been logged. This is bad, but it seems Meta caught the problem themselves and were transparent about it. It’s unclear to me what the DPC was investigating for five years.