NSFileExtendedAttributes com.apple.rootless for NSTemporaryDirectory when doing archive build for macOS app QuickLook plugin on Big Sur

Hello there 🤓

We have this elderly QuickLook plugin that I am trying to revive for Big Sur... (Well, it seems to be a problem on Big Sur only.)

The thing is that it uses NSTemporaryDirectory(). This directory can be written to when built locally in Debug/Release configuration.

But when doing an Archive/Notarized builds the plugin cannot write to the directory. I have here found that in this case it gets its NSFileExtendedAttributes set to com.apple.rootless! So somehow System Integration Protection (SIP) kicks-in!

I have found two workarounds:

  1. If I disable SIP ($ csrutil disable from Recovery mode) then it works.

  2. If I enable the Hardened Runtime exception 'Allow DYLD Environment Variables' then is also gets write access to the temp directory.

My question is: Can one give a proper explanation for why SIP kicks-in? Could we have misconfigured something?

Let me know if you need additional information, thanks.

Best regards,

Jens Schwarzer.

Is NSTemporaryDirectory returning the same path in both cases?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Hi Quinn! I was almost betting $100 that you - the Forum's one-man army - would reply! :D

Yes, it is the same path in both cases. The only difference is the NSFileExtendedAttributes com.apple.rootless when running the Archive-build.

Thanks!

Best regards,

Jens :)

Yes, it is the same path in both cases.

Hmmm. The symptoms you’re describing don’t make sense. If a directory is protected by SIP then it’s always protected by SIP, regardless of how the client code was built or executed. That’s kinda the whole point (-:

What is this path being returned by NSTemporaryDirectory?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Hi again :)

I'm really sorry; just reran and found that the paths were actually different 🙈

I've added this code piece to show the difference:

    NSLog(@"Quinn: NSTemporaryDirectory(): %@", NSTemporaryDirectory());
    NSError *error = nil;
    NSDictionary *dictionary  = [NSFileManager.defaultManager attributesOfItemAtPath:NSTemporaryDirectory() error:&error];
    NSLog(@"Quinn: error: %@", error);
    NSLog(@"Quinn: dictionary: %@", dictionary);

Debug:

2021-06-23 12:35:30.315 QLICProcessor[71421:3730283] Quinn: NSTemporaryDirectory(): /var/folders/_h/cbm2fp054c9byr188mdyxhw00000gp/T/com.apple.quicklook.qlmanage/
2021-06-23 12:35:30.315 QLICProcessor[71421:3730283] Quinn: error: (null)
2021-06-23 12:35:30.316 QLICProcessor[71421:3730283] Quinn: dictionary: {
    NSFileCreationDate = "2021-06-18 20:22:23 +0000";
    NSFileExtensionHidden = 0;
    NSFileGroupOwnerAccountID = 20;
    NSFileGroupOwnerAccountName = staff;
    NSFileModificationDate = "2021-06-23 10:30:11 +0000";
    NSFileOwnerAccountID = 502;
    NSFileOwnerAccountName = jsc;
    NSFilePosixPermissions = 448;
    NSFileProtectionKey = NSFileProtectionCompleteUntilFirstUserAuthentication;
    NSFileReferenceCount = 16;
    NSFileSize = 512;
    NSFileSystemFileNumber = 32688057;
    NSFileSystemNumber = 16777220;
    NSFileType = NSFileTypeDirectory;
}

and archive:

2021-06-23 12:28:13.608 QLICProcessor[62356:3702628] Quinn: NSTemporaryDirectory(): /var/folders/_h/cbm2fp054c9byr188mdyxhw00000gp/T/
2021-06-23 12:28:13.608 QLICProcessor[62356:3702628] Quinn: error: (null)
2021-06-23 12:28:13.609 QLICProcessor[62356:3702628] Quinn: dictionary: {
    NSFileCreationDate = "2021-05-17 13:09:39 +0000";
    NSFileExtendedAttributes =     {
        "com.apple.rootless" = {length = 7, bytes = 0x666f6c64657273};
    };
    NSFileExtensionHidden = 0;
    NSFileGroupOwnerAccountID = 20;
    NSFileGroupOwnerAccountName = staff;
    NSFileModificationDate = "2021-06-23 10:20:49 +0000";
    NSFileOwnerAccountID = 502;
    NSFileOwnerAccountName = jsc;
    NSFilePosixPermissions = 448;
    NSFileProtectionKey = NSFileProtectionCompleteUntilFirstUserAuthentication;
    NSFileReferenceCount = 1958;
    NSFileSize = 62656;
    NSFileSystemFileNumber = 529943;
    NSFileSystemNumber = 16777220;
    NSFileType = NSFileTypeDirectory;
}

The command I use to start the app: qlmanage -p -c com.mycompany.myfile -g MyQLGenerator.qlgenerator ~/Desktop/MyFile.xyz

Update: If I enabled the Hardened Runtime exception 'Allow DYLD Environment Variables' I also get the working path /var/folders/_h/cbm2fp054c9byr188mdyxhw00000gp/T/com.apple.quicklook.qlmanage/...

Thanks! :)

OK, this is starting to make more sense.

If you test without using qlmanage, by actually previewing a file, does it work without com.apple.security.cs.allow-dyld-environment-variables?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

NSFileExtendedAttributes com.apple.rootless for NSTemporaryDirectory when doing archive build for macOS app QuickLook plugin on Big Sur
 
 
Q