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.

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];


On 24 Feb 2022, at 9:07 pm, Graham Cox <graham@...> wrote:

Hi Glenn,

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 = [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?


On 24 Feb 2022, at 6:44 pm, Glenn L. Austin <glenn@...> wrote:

On Feb 23, 2022, at 11:30 PM, Graham Cox <graham@...> wrote:

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>

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.

Glenn L. Austin, Computer Wizard and Race Car Driver         <><

Join to automatically receive all group messages.