App cannot write file after being sandboxed

I have this app, ZipEnc, which has worked quite fine for years, up until now.

This is below what I get in Console when I try to save from the app once sandboxed in App Wrapper to go to the MAS.

I will appreciate any guidance.

Thank you in advance.

[code]Sandbox: ZipEnc(31735) deny(1) file-write-create /Users/michelbujardet/Documents/MatchFonts/1-Development/ZipEnc/Builds - ZipEnc 304/OS X 64 bit/Wrapped (MAS) Application/TestFile
Violation: deny(1) file-write-create /Users/michelbujardet/Documents/MatchFonts/1-Development/ZipEnc/Builds - ZipEnc 304/OS X 64 bit/Wrapped (MAS) Application/TestFile
Process: ZipEnc [31735]
Path: /Users/michelbujardet/Documents/MatchFonts/1-Development/ZipEnc/Builds - ZipEnc 304/OS X 64 bit/Wrapped (MAS) Application/ZipEnc.app/Contents/MacOS/ZipEnc
Load Address: 0x10b961000
Identifier: com.matchsoftware.ZipEnc
Version: 3.0.4 (3.04)
Code Type: x86_64 (Native)
Parent Process: launchd [1]
Responsible: /Users/michelbujardet/Documents/MatchFonts/1-Development/ZipEnc/Builds - ZipEnc 304/OS X 64 bit/Wrapped (MAS) Application/ZipEnc.app/Contents/MacOS/ZipEnc
User ID: 501

Date/Time: 2020-04-15 00:09:57.058 GMT+2
OS Version: Mac OS X 10.15.4 (19E287)
Report Version: 8

MetaData: {“summary”:“deny(1) file-write-create \/Users\/michelbujardet\/Documents\/MatchFonts\/1-Development\/ZipEnc\/Builds - ZipEnc 304\/OS X 64 bit\/Wrapped (MAS) Application\/TestFile”,“build”:“Mac OS X 10.15.4 (19E287)”,“normalized_target”:[“Users”,“michelbujardet”,“Documents”,“MatchFonts”,“1-Development”,“ZipEnc”,“Builds - ZipEnc 304”,“OS X 64 bit”,“Wrapped (MAS) Application”,“TestFile”],“action”:“deny”,“operation”:“file-write-create”,“pid”:31735,“rdev”:0,“file-flags”:0,“platform_binary”:“no”,“errno”:1,“vnode-type”:“REGULAR-FILE”,“storage-class”:“kTCCServiceSystemPolicyDocumentsFolder”,“profile-flags”:0,“matched-user-intent-extension”:false,“team-id”:“3T278B9D74”,“profile-in-collection”:false,“platform-binary”:false,“process-path”:"\/Users\/michelbujardet\/Documents\/MatchFonts\/1-Development\/ZipEnc\/Builds - ZipEnc 304\/OS X 64 bit\/Wrapped (MAS) Application\/ZipEnc.app\/Contents\/MacOS\/ZipEnc",“signing-id”:“com.matchsoftware.ZipEnc”,“platform-policy”:false,“mount-rdev”:16777234,“target”:"\/Users\/michelbujardet\/Documents\/MatchFonts\/1-Development\/ZipEnc\/Builds - ZipEnc 304\/OS X 64 bit\/Wrapped (MAS) Application\/TestFile",“apple-internal”:false,“matched-extension”:false,“flags”:5,“path”:"\/Users\/michelbujardet\/Documents\/MatchFonts\/1-Development\/ZipEnc\/Builds - ZipEnc 304\/OS X 64 bit\/Wrapped (MAS) Application\/TestFile",“hardware”:“Mac”,“responsible-process-path”:"\/Users\/michelbujardet\/Documents\/MatchFonts\/1-Development\/ZipEnc\/Builds - ZipEnc 304\/OS X 64 bit\/Wrapped (MAS) Application\/ZipEnc.app\/Contents\/MacOS\/ZipEnc",“responsible-process-uid”:501,“primary-filter-value”:"\/Users\/michelbujardet\/Documents\/MatchFonts\/1-Development\/ZipEnc\/Builds - ZipEnc 304\/OS X 64 bit\/Wrapped (MAS) Application\/TestFile",“responsible-process-user-uuid”:“14EEA2D4-FB58-4BD8-BF89-44571F8D3363”,“container”:"\/Users\/michelbujardet\/Library\/Containers\/com.matchsoftware.ZipEnc\/Data",“process”:“ZipEnc”,“primary-filter”:“path”,“uid”:501,“suffix”:“TestFile”}
[/code]

   "storage-class":"kTCCServiceSystemPolicyDocumentsFolder",

Total guess, but it might have something to do with trying to access a file in the documents folder and at some point permission to Documents was denied. I know that one time opening a file with Firefox made the “Do you want to let Firefox access the Pictures folder?” dialog appear.

This might help with resetting that permission, it looks kind of relevant when I run it through the translator: https://qiita.com/IKEH/items/323db8b5ea1a1a28a519

My other guess would be that you used GetFolderItem on Catalina based on this:

   "target":"\\/Users\\/michelbujardet\\/Documents\\/MatchFonts\\/1-Development\\/ZipEnc\\/Builds - ZipEnc 304\\/OS X 64 bit\\/Wrapped (MAS) Application\\/TestFile",

But I’m sure you know that one :slight_smile:

Wow! I have never seen an exception report, where the contents are in JSON, I guess at least its not in bplist.

My guess is the same as @Tim Parnell s second, in that for some reason you don’t have access to this file.

/Users/michelbujardet/Documents/MatchFonts/1-Development/ZipEnc/Builds - ZipEnc 304/OS X 64 bit/Wrapped (MAS) Application/TestFile

OK. Thank you. I am going to continue investigating. Apparently, it is yet another one of those Catalina security things that broke my app…

I will report my findings.

by the time we will be aware of all catalina annoying security , the next os will be there, with new ones !

The plot thickens: when the app is not sandboxed, and it tries to save, say, to Documents, macOS asks for permission.

When the app is sandboxed, writing is simply denied.

How would I go to ask for permission to write ?

How do you handle the sandboxing?

Are you asking the user for a foldername before saving?
Did you ask for Read/write permissions for Save Dialogs in AppWrappers Capabilities tab?

App Wrapper. As I have been doing since 2013 or so :slight_smile:

[quote=484052:@Jeff Tullin]Are you asking the user for a foldername before saving?
Did you ask for Read/write permissions for Save Dialogs in AppWrappers Capabilities tab?[/quote]

Yes, I do get confirmation from the user to open the folder, and yes, I made sure to put read/write Save in AW.

Without sandboxing, Catalina asks for confirmation when the app tries to access the folder. Once sandboxed, it simply fails with the error I posted.

I suspect I will have to specifically get a dialog to save file by file. That will kill any possibility to process multiples files in a drop over the app. Thanks Catalina :confused:

[quote=484069:@Michel Bujardet]App Wrapper. As I have been doing since 2013 or so :slight_smile:

Yes, I do get confirmation from the user to open the folder, and yes, I made sure to put read/write Save in AW.

Without sandboxing, Catalina asks for confirmation when the app tries to access the folder. Once sandboxed, it simply fails with the error I posted.

I suspect I will have to specifically get a dialog to save file by file. That will kill any possibility to process multiples files in a drop over the app. Thanks Catalina :/[/quote]
Yes, you must use the dialog to get permission to access the file. This is not a new restriction. That’s how it has always been.

I understand, Thom. Except until Catalina, I could create a file in the same folder the file I compress was.

It is no longer the case.

I cannot anymore select a folder where to save files either. Any attempt to write there fails.

Just to explain why you’re seeing what you are, technically the user never gave you access to the folder. They provided you the item. It’s a security measure that makes sense. If I provide you access to /Users/tim/Code/MichelsProject, the intent is definitely only to allow access MichelsProject and not the entire Code folder.

The security logic is here, indeed. My point was never to question the wisdom of the powers that be. I bow to the almighty priests of the fruit :stuck_out_tongue:

Problem is, there are a good number of apps that let you drop a bunch of files onto it, and save automatically the converted files.

That was the case of my app until now. Apple reviewers even validated these apps so they are in the MAS. Fortunately, I got a report from a Catalina user about what was happening.

I am now modifying the couple apps I have, which are now impaired, so they save in a subfolder within specialFolder.ApplicationData. A button will let the user access that folder.

and how do you show the user a dialog asking permission to write a file in the document folder or the desktop ?

A thought: if it won’t allow you to select a folder and save the individual files, could you allow the user to select a single file target?
If so, you might assemble the collection of files in ApplicationData, zip them up, and save one Zip file at the place where the user lets you have access to.

I don’t. Files will be written exclusively within the destination folder, in ApplicationData.

[quote=484144:@Jeff Tullin]A thought: if it won’t allow you to select a folder and save the individual files, could you allow the user to select a single file target?
[/quote]

I could, and it would work, if precisely that did not defeat the entire purpose of the app, where users can drop many files and folders to be compressed as a batch.

The solution of having the app write in the ApplicationData subfolder is the only one that will prevent the need to seek authorization to write, or risk having a deny from the system.

For an application that I will be submitting to the App Store, once they stop making me make changes to my current one, I faced the exact same problem. I’m not saying you should do it the way how I did, but merely letting you know what I did.

In my application I have a popup menu, the default item is to “Ask every time”, so when a user drags a file or bunch of files into the application it uses a SelectFolderDialog to “Ask” where the user want’s to save the files too.

Also in the popup menu is an option whereby the user can select a destination and have the processed files written to that destination without being asked. For this I have to use Security-Scoped Bodgemarks (an alternative option is to use the Apple Recent Items API, but I thought that might be a little weird), they do/will fail especially when upgrading the OS! But it’s what I got at the moment.

I used to be able to make a hard link to a file and folder as a way of holding onto access, but Apple figured it out and closed that one.

For a future version I want to use a custom SelectFolderDialog, so when the application is in “Ask” mode, the user can select a checkbox when browsing and the application will then use that chosen location until the user manually selects another.

Hope this helps. But yeah, I’m frustrated at all the extra work we have to put in, to make less sales than we did 5, 10, 15 years ago.

Except in one situation that I’m aware of. If you have too many Security-Scoped Bodgemark failures, this can corrupt the Container data, and then your application is locked out of everywhere except it’s bundle. The container has to be manually deleted, before the application can use that location again.

I would recommend double checking that folder to see if you can write to it before you try, some customers had locked temporary folders with Catalina, so I would expect that this folder can be locked by an OS update also.

Thank you. I always assumed it was possible to write there.

If an idiot finds a way to lock it, though, some of my apps will be severely impaired. For instance, Check Writer has to store settings somewhere, in particular critical things such as account numbers, user details…

I don’t think it would be acceptable to require users to enter that information each time they launch the app.

“File access considered unsafe” is Crapolina’s motto for me. Knock on wood: so far I haven’t had problems with preferences or temp folder in the MAS version.

Sadly the only idiotic thing a customer has to do, is to install Catalina. This very act locked the temporary folder for some of my customers.

It broke my atomic saving code. Someone on Twitter suggested I use Apple’s “Recommended” functions for atomic saving, so I switched to those.

A couple of weeks later I started getting error reports that some customers once again couldn’t save. Upon investigation, I discovered that Apple’s Atomic functions leave behind an empty folder (in the very same Temporary folder that I can’t write too), once the temporary folder reaches the limit of 512 ‘things’ no more files can be added to that folder. Like normal (now) the documentation for these functions makes no mention of this.

We’ve all suffered some weird issues throughout time, but Catalina…

I could suggest NSUserDefaults, but I won’t. I’d actually recommend using the KeyChain for this information, you can hack it so you can create a complex record to store all the user information. The main advantage of the KeyChain is that the information is stored securely, it’s out of reach for normal applications (unless the user authorizes them to access it and because it’s encrypted on disk, it prevent a mischievous 3rd party app from reading your data files).

But it is more work, and none of us want to hear that right now :slight_smile: