Re: Verbose warning splurged to the log with Secure Coding (dearchiving) -- can they be serious?
Graham Cox
This sounds so right. But unfortunately doesn’t work for __NSCFConstantString, which returns that, and not NSString. I haven’t yet tried on other classes, but most of the time it’ll be a string...
toggle quoted messageShow quoted text
In respect of this particular issue, I think if you call `classForCoder` rather than `class` on the object of interest, you'll get the portable class name ("NSString") you're looking for.
|
|
Re: Verbose warning splurged to the log with Secure Coding (dearchiving) -- can they be serious?
Quincey Morris
I think you’re Doing It Wrong™. Your solution is effectively disabling secure coding, which solves your run-time error, but leaves you with the exact security vulnerability that secure coding is supposed to protect against. Your goal of “I want it to be as flexible as possible” without specifying classes in advance isn’t compatible with secure decoding. Let’s stick with your NSDictionary example. There are 3 cases: 1. You (try to) decode the dictionary and specify class NSDictionary. This is insecure, because decoding the dictionary also decodes arbitrary classes contained in the dictionary. 2. The dictionary contains only objects of “plist” classes such as NSNumber, NSDate and standard NS collection classes. There are a finite number of these, so you can always list them all in `decodeObjectOfClasses:forKey:`, and this kind of dictionary is useful for a lot of things without getting into custom classes. 3. The dictionary contains your custom classes and/or client code's custom classes as well. Again, you must use `decodeObjectOfClasses:forKey:` to specify *all* of the classes that might be in the dictionary, but you don’t know them all at compile time. You can’t do #1, so you must do #2 or #3. Either way, use `decodeObjectOfClasses:forKey:` for a heterogenous collection or hierarchy. Note that your set of classes for `decodeObjectOfClasses:forKey:` can be built at run-time, but you should avoid the temptation to encode that set into the archive, since that also compromises security. (An attacker can simply ask your code to unarchive data containing malicious classes, and naming their classes!) If you want to make things flexible for client code, I guess the way to do it would be to have the client tell you, on unarchiving, the list of its custom classes that it allows in the archive. You’d augment that set with the additional classes your own wrapper code needs, and specify that for `decodeObjectOfClasses:forKey:`.
|
|
Re: Verbose warning splurged to the log with Secure Coding (dearchiving) -- can they be serious?
On 24 Feb 2022, at 2:07 am, Graham Cox <graham@mapdiva.com> wrote:In respect of this particular issue, I think if you call `classForCoder` rather than `class` on the object of interest, you'll get the portable class name ("NSString") you're looking for. -ben
|
|
Re: Verbose warning splurged to the log with Secure Coding (dearchiving) -- can they be serious?
Graham Cox
Well, I figured out a solution, though I’m not sure — it seems slightly smelly, even though it looks neat from the outside and is easy to use. Would appreciate any feedback.
toggle quoted messageShow quoted text
Basically, I walk up the class hierarchy until I hit NSObject, then return the class once removed from that. Then I added a category on NSCoder that uses this to encode that class name in the archive. Using these methods in NSCoding is easy and hides the minor pain involved. Class GCLowestSpecificAncestorClass( Class aClass ) { // walks back up the class hierarchy from <aClass> until it reaches NSObject (or nil), and returns the // class that subclasses NSObject. Class sc = [aClass superclass]; while( sc && sc != [NSObject class]) { aClass = sc; sc = [aClass superclass]; } return aClass; } @implementation NSCoder (GCSecureAnonymousClassSupport) - (void) encodeAnonymousObject:(id) theObject forKey:(NSString*) key { Class umbrella = GCLowestSpecificAncestorClass([theObject class]); NSAssert( umbrella != [NSObject class], @"cannot archive NSObject as anonymous class"); NSString* className = NSStringFromClass( umbrella ); [self encodeObject:className forKey:[NSString stringWithFormat:@"class_for_%@", key]]; [self encodeObject:theObject forKey:key]; } - (id) decodeAnonymousObjectForKey:(NSString*) key { NSString* className = [self decodeObjectOfClass:[NSString class] forKey:[NSString stringWithFormat:@"class_for_%@", key]]; Class umbrella = NSClassFromString( className ); return [self decodeObjectOfClass:umbrella forKey:key]; } @end
|
|
Re: Verbose warning splurged to the log with Secure Coding (dearchiving) -- can they be serious?
Graham Cox
Hi Glenn,
toggle quoted messageShow quoted text
This seemed like a perfectly fine idea in this case, so I tried it. Now I get a new message spewed to the log: 2022-02-24 20:50:13.158117+1100 GCSimpleContainers[26354:31119213] [general] *** -[NSKeyedUnarchiver validateAllowedClass:forKey:] allowed unarchiving safe plist type ''NSString' (0x7ff85c670920) [/System/Library/Frameworks/Foundation.framework]' for key 'data', even though it was not explicitly included in the client allowed classes set: '{( "'__NSCFConstantString' (0x7ff85c645908) [/System/Library/Frameworks/CoreFoundation.framework]" )}'. This will be disallowed in the future. This happens for the line that decodes the payload object, which happens to be a string. My code is: Class dataClass = NSClassFromString([coder decodeObjectOfClass:[NSString class] forKey:@"data_class"]); //<—— this is OK self.data = [coder decodeObjectOfClass:dataClass forKey:@"data”]; //<— this is not The actual class is __NSCFConstantString, rather than just a generic NSString, that seems to be what it is complaining about — if I change it to use [NSString class] it’s fine. Since the archive originally wrote the result of NSStringFromClass(), it will of course write the explicit class rather than the more general umbrella class of a cluster. Can you think of a simple solution for this, in general? —G.
|
|
Re: Verbose warning splurged to the log with Secure Coding (dearchiving) -- can they be serious?
Glenn L. Austin
A suggestion? Archive the class name as a part of your archiving process, then get the class instance by NSClassFromString. You can then use that as the parameter for decodeObjectOfClass:forKey:. It's not entirely secure, it's not the best style to avoid the warning, but it should prevent the spew into the system log. Also, if you can't get the class from the class name, you know you'll not be able to decode the value anyway.
|
|
Verbose warning splurged to the log with Secure Coding (dearchiving) -- can they be serious?
Graham Cox
Hi all,
I was working on some demo code investigating the use of secure archiving, since I guess we all have to adopt that if we can. I have a simple container class (a linked list) that I decided to make secure archivable. It works, but when dearchiving, I need to dearchive the ‘payload’ of the list nodes, which can be anything at all - it’s defined as an id<NSObject>. So when I ask for this item securely, I use -decodeObjectOfClass:[NSObject class] forKey:<blah blah> But the dearchiver spits this to the log: 2022-02-24 17:59:55.701579+1100 GCSimpleContainers[25591:31009796] [general] *** -[NSKeyedUnarchiver validateAllowedClass:forKey:]: NSSecureCoding allowed classes list contains [NSObject class], which bypasses security by allowing any Objective-C class to be implicitly decoded. Consider reducing the scope of allowed classes during decoding by listing only the classes you expect to decode, or a more specific base class than NSObject. This will become an error in the future. Allowed class list: {( "'NSObject' (0x7ff85c7c2b88) [/usr/lib]" )} I get what it’s saying — that asking for NSObject is too open-ended, and it renders the secure coding moot. But what else can I do? I don’t know the payload class, I want it to be as flexible as possible. Forcing this to be a subclass of NSObject of my own means I lose the ability to store all standard Cocoa objects ‘as is’ in my container. Adding a wrapper class doesn’t help because it would still need to archive what it wrapped. It strikes me that Apple themselves must run into this when archiving NSDictionary, since keys can be anything, but that works, so perhaps they use an internal bit of trickery. It concerns me that they say “this will become an error in the future”. I can go back to traditional archiving with no security, no errors there, but then what’s the point of secure coding? A way to simply suppress the log of the message would do for now. It’s extra bad because it logs this every time it happens, not just once. Is this a case of Apple being too zealous in overlooking a common use-case, or have I missed something? —G
|
|
UICollectionView with DiffableDataSource
Xcode 13.1, iOS 25 SDK
I have a UICollectionView (with a custom UICollectionViewLayout) which I am updating with a DiffableDataSource. This CollectionView displays a particular data object (with a given number of sections and items).
The user can choose to display a different object (with a different number of sections and items), reusing this CollectionView. When this occurs, I do the following:
(pass the new data object to the custom layout)
let layout = collectionView.collectionViewLayout
layout.invalidateLayout()
collectionView.contentSize = layout.collectionViewContentSize
(calculate a new snapshot and apply it)
When the new data object has FEWER sections and/or items as the first, I get a series of warning messages (one for each of the cells that are no longer in the collection view) as follows:
2021-12-07 14:29:02.239301-0600 WineCorner[82916:1921357] [CollectionView] Layout attributes <UICollectionViewLayoutAttributes: 0x7f77b3047e00> index path: (<NSIndexPath: 0xa0f0b1eb018e754a> {length = 2, path = 0 - 4}); frame = (578.118 6; 160 160); transform = [0.70710678118654757, -0.70710678118654746, 0.70710678118654746, 0.70710678118654757, 0, 0]; zIndex = 1; were received from the layout <WineCorner.WineRackLayout: 0x7f77b1f1a0c0> but are not valid for the data source counts. Attributes will be ignored.
Obviously, I am not handling the situation correctly. What should I do so that these warning messages are not issued?
|
|
NSTextView: displaying "virtual" symbols?
David Young
[I'd sent this to cocoa-dev@lists.apple.com, but ISTR that list is
deprecated. Resending here.] I am working on a document storage format that consists of logical zones that nest. You can think of them sort of like <div> elements from (X)HTML: <div id="foo"><div id="bar">All work and no play.</div></div> Ordinarily, I would like for the zone boundaries marked by <div> and </div> to be invisible to the user. Ordinary cursor motion commands should step from character to character, ignoring the <div> boundaries. However, I also want to offer a display & editing mode to the user where they can see the boundaries and use special cursor motion commands to "creep" the cursor across the boundaries. In this mode, there are additional locations addressable by the cursor. I have marked those locations with a pipe (|): |<div id="foo">|<div id="bar">All work and no play.</div>|</div>| I took the attached screenshot in Numbers. It shows roughly the visual effect I'm looking for. Incidentally, it's possible to move the cursor back and forth over the crescent that "closes" the AVERAGE function cell. That's good. It is also possible to delete the crescent, which is neither necessary nor desirable for my purposes, but I guess that I could accept it. It would be nice if I could accomplish this effect without introducing characters to my NSTextStorage. It looks like TextKit 2 lets one do something like this rather easily, but I'm leary of adopting it while it's so green. Is anyone aware of a "worked example" I can read for TextKit 1? Dave -- David Young dyoung@pobox.com Urbana, IL (217) 721-9981
|
|
Re: Scanner oddity
Sandor Szatmari
Laurent,
On Sep 29, 2021, at 15:11, Laurent Daudelin <laurent@...> wrote:
Have you tried -setCharactersToBeSkipped: Set that to skip new line, carriage return… Maybe that will work for you? Sandor
|
|
Scanner oddity
Laurent Daudelin
Anybody uses the Scanner class?
I’m using an instance to extract some data from a string received from a web server. If I have a string that is “45\nBlah”, read the “45”, the scanner location is just before the carriage return. If I then try a someString = scanner.scanString(“\nBlah”), someString is nil. But if I do scanner.scanLocation += 1, then someString = scanner.scanString(“Blah”), then someString contains “Blah”. Not sure if I’m using it correctly or if there is some kind of a bug. By the way, speaking of “scanLocation”, the editor gives me a warning that it’s been deprecated as of iOS 13. But when I open the documentation about the Scanner, there is no mention that it’s been deprecated. Further, the editor doesn’t suggest a replacement.
|
|
How to embed Swift Package executable into macOS app
Jim
I have a macOS app I’d like to embed an executable from a swift package. However, while I can add the swift package under the app target’s “Frameworks, Libraries, and Embedded Content” section, and add it to Dependencies in Build Phases, it doesn’t show up as a project resource in the “Copy Bundle Resources” section. Is there some step I’m missing?
Also, I had accidentally dragged the executable to my project and added that in the “Copy Bundle Resources” section, but when I tried to notarize it refused because the executable wasn’t built with hardened runtime. Is it possible to build a command-line executable from a Swift package with hardened runtime? This is all pointing me back to how I had first added this, with a separate target and scheme in the main project for the command line tool. However, that also added the command line tool as a product, and even though I turned off “Archive” in the scheme for the command line tool it was still archived as a separate product. This archived as a folder with both products and I wasn’t able to use Xcode’s built-in notarization process. I can notarize outside of Xcode if I have to but it doesn’t seem like this should be so difficult. Also I’d prefer to have the command line tool in its own project if possible. Jim Crate
|
|
Re: Async/Await and Model Dialogs
also you can enlargen your screen resolution:
toggle quoted messageShow quoted text
apple->system prefs->displays->display resolution: scaled, click "more space" on the far right -dave
|
|
Async/Await and Model Dialogs
In a UIKit context, has anyone had experience/success in using async/await to synchronize a modal dialog with other logic? I've tried it a bit without success.
I.e, given a presented dialog, I want to capture data in the dialog, then use the results in a simple, linear fashion. (Something that looks like "Present the dialog, wait for results, use results" -- all inline.) It seems to me that async/await with @MainActor ought to make that possible, but I haven't yet figured out how. I'd really like to see a real-world example. Can you help?
|
|
Re: Just a little sharing - it's nice when your product finally hits the market.
Alex Zavatone
I don’t know. I was at MorphoTrust in 2014 when we worked on what would become the Apple Drivers’ Licence app. I did the first iOS working prototype with Dan, Ted and Clayton. Our PM was Steve Miu. Since then, MorphoTrust has gone through a few corporate hands. It was even owned by a French company for a while. Not sure who owns it now. It took forever to get the product picked up from what I know. Would have loved to be still working on it!
toggle quoted messageShow quoted text
Cheers! Alex Zavatone
On Sep 1, 2021, at 3:14 PM, Jack Brindle via groups.io <jackbrindle=me.com@groups.io> wrote:
|
|
Re: Just a little sharing - it's nice when your product finally hits the market.
Jack Brindle
Louisiana has had a driver’s license app for several years. Is that your work, Alex?
toggle quoted messageShow quoted text
Jack
On Sep 1, 2021, at 2:32 PM, Alex Zavatone via groups.io <zav=mac.com@groups.io> wrote:
|
|
Just a little sharing - it's nice when your product finally hits the market.
Alex Zavatone
My olden app has finally hit the market.
https://www.macrumors.com/2021/09/01/apple-shares-us-states-adopting-wallet-ids/ It’s only taken 7 years since I worked on it. : ) Cheers to everyone else who was able to bring it to market. Best, Alex Zavatone
|
|
WKWebKit and iOS 13 in Xcode 12
Alex Zavatone
Has anyone found a workaround for the crash of WKWebKit under the above configuration? Xcode reposts “Error acquiring assertion” trying to display any webpage.
A workaround to prevent the screen from blanking out is this, but it doesn’t stop WKWebKit from crashing. override func willMove(toParent: UIViewController? ) { print("Something") } Basically, loading any webpage crashes out in WebKit, iOS 13 and Xcode 12. It’s fine in iOS 14. Thanks in advance. Alex Zavatone
|
|
Re: New syntax in Xcode 12.5.
Alex Zavatone
I found out what the issue was. The programmer didn’t add a self in front of variables that had the same name as the local that he was creating. Xcode 12.4 reports an error until you add self in front of the properties. Xcode 12.5 can handle
toggle quoted messageShow quoted text
The actual line looked more like this. let myVar = myVar != someValue ? myVar : myOtherAssignment It actually should be let myVar = self.myVar != someValue ? self.myVar : myOtherAssignment Thanks. Alex Zavatone
|
|
Re: New syntax in Xcode 12.5.
Jeremy Hughes
1. myVar != someValue is the condition.
toggle quoted messageShow quoted text
2. It determines whether the ternary expression evaluates to resultOne or resultTwo 3. resultOne or resultTwo is what is assigned in let myVar = This seems like a standard use of the ternary conditional operator. I don’t have any problems compiling it in Xcode 12.4. Jeremy —
On 26 Jul 2021, at 16:57, Alex Zavatone via groups.io <zav=mac.com@groups.io> wrote:
|
|