Sandboxing the DemoRunner

Hi there,
I have some trouble with an OSX app distributed on the Apple Store.
It has been one month since I first notified Apple, still trying to find a solution.
So I tried as a test, to apply sandboxing to the JUCE OSX Demorunner. And, as for my app, the result was that the user can’t access outside its container.
BUT if I understand well my readings and as I have been told by the Apple Support, “The user can dynamically extend your sandbox by various user-level actions (the open and save panels, drag and drop, AppleScript).”. Isn’t the basic FileBrowser able to allow the user to do such a thing? Because they also suggested to use NSDocument and NSDocumentController … This is not a path I would like to take using JUCE.

JUCE uses an NSOpenSavePanelDelegate internally in the FileChooser.

This SO answer, cocoa - NSSavePanel and the Sandbox - Stack Overflow, provides this information:

After contacting Apple, I can confirm what Rob Keniger wrote: NSOpenSavePanelDelegate method’s don’t have access to the filesystem in sandboxed applications.

Ooh, thank you so much t0m. Should we infer that we can’t publish a signed OSX app with JUCE, within which the user will have the possibility to navigate outside the app container? I would be so surprised not to have seen other people complaining.

It appears that SO link was only for the NSOpenSavePanelDelegate's methods itself. NSOpenPanel should work. Have you tried enabling User Selected File in the sandboxing settings?

I have checked com.apple.security.files.user-selected.read-write = true.
About NSOpenPanel: Apple answered me that " You typically [extend your sandbox] by using the open and save panels (NSOpenPanel and NSSavePanel). If your app uses the standard Cocoa document architecture (NSDocument and NSDocumentController) this mostly works by default. "
For some reason I had’nt seen that FileChooser uses NSOpenPanel. So it should work - but it doesn’t.
Also, a problem seems to show itself when I compile with “debug executable” on. The app breaks around the point below:

0x7fff6cff5af2 <+1873>: leaq   0x11f5(%rip), %r8         ; "Sandbox registration internal error: %s"

I have been troubleshooting the same issue today with Open/Save dialogs in a Sandboxed app on macOS. I’m building on macOS 12, where it works fine, but I had a report of the dialogs not working on an older macOS. So I’ve been testing on 10.11 (El Capitan) and I can reproduce the broken dialogs there.

If I don’t include an entitlements file when codesigning my app, it actually works fine on 10.11.

However, if I do include the entitlements file (which has the entry for com.apple.security.files.user-selected.read-write), when the app is supposed to show an open or save dialog, it does nothing.

Looking in the Console app, I see errors shown like these:

SaveSavePanel_e57cba400d957299 is not a supported subclass for sandboxing

or

SaveOpenPanel_fa4915e8e75dbbeb is not a supported subclass for sandboxing

(Side note: the “SaveSave” wording looks weird on those – I’m pretty sure that’s due to a typo in juce_mac_FileChooser.mm, and it should be “SafeSave” and “SafeOpen” instead. I just submitted a pull request to address that.)

Anyways, fixing that typo didn’t make the sandboxed app work correctly in 10.11. Any other ideas as to what might be broken here, or should I just give up on sandboxing the app?

Here is the full error message with the trace, as appears in Console when trying to show a Save dialog:

1/10/23 2:00:08.733 PM MyApp[3790]: SaveSavePanel_e57cba400d957299 is not a supported subclass for sandboxing

1/10/23 2:00:08.896 PM MyApp[3790]: (
	0   CoreFoundation      0x00007fff92ead452 __exceptionPreprocess + 178
	1   libobjc.A.dylib     0x00007fff9971e73c objc_exception_throw + 48
	2   CoreFoundation      0x00007fff92f1449d +[NSException raise:format:] + 205
	3   AppKit              0x00007fff9a864433 +[NSSavePanel newRemotePanel] + 157
	4   AppKit              0x00007fff9ac70f40 -[NSSavePanel initWithContentRect:styleMask:backing:defer:] + 94
	5   AppKit              0x00007fff9a8648c0 -[NSPanel init] + 87
	6   MyApp               0x000000010c2db56d _ZN4juce11FileChooser6NativeC2ERS0_iPNS_20FilePreviewComponentE + 669
	7   MyApp               0x000000010c2db13b _ZN4juce11FileChooser6NativeC1ERS0_iPNS_20FilePreviewComponentE + 43
	8   MyApp               0x000000010c2db093 _ZNSt3__120__shared_ptr_emplaceIN4juce11FileChooser6NativeENS_9allocatorIS3_EEEC2IJRS2_RiRPNS1_20FilePreviewComponentEEEES5_DpOT_ + 163
	9   MyApp               0x000000010c2dad5d _ZNSt3__120__shared_ptr_emplaceIN4juce11FileChooser6NativeENS_9allocatorIS3_EEEC1IJRS2_RiRPNS1_20FilePreviewComponentEEEES5_DpOT_ + 45
	10  MyApp               0x000000010c2dac34 _ZNSt3__1L15allocate_sharedIN4juce11FileChooser6NativeENS_9allocatorIS3_EEJRS2_RiRPNS1_20FilePreviewComponentEEvEENS_10shared_ptrIT_EERKT0_DpOT1_ + 148
	11  MyApp               0x000000010c10f257 _ZNSt3__1L11make_sharedIN4juce11FileChooser6NativeEJRS2_RiRPNS1_20FilePreviewComponentEEvEENS_10shared_ptrIT_EEDpOT0_ + 103
	12  MyApp               0x000000010c054457 _ZN4juce11FileChooser18showPlatformDialogERS0_iPNS_20FilePreviewComponentE + 55
	13  MyApp               0x000000010c054030 _ZN4juce11FileChooser11createPimplEiPNS_20FilePreviewComponentE + 368
	14  MyApp               0x000000010c053ce8 _ZN4juce11FileChooser10showDialogEiPNS_20FilePreviewComponentE + 56
	15  MyApp               0x000000010c053e83 _ZN4juce11FileChooser19browseForFileToSaveEb + 51
	16  MyApp               0x000000010c3f6937 _ZN14UserDataKeeper14exportAllAsZipEv + 1415
	17  MyApp               0x000000010bc42227 _ZZN13SettingsPanelC1EvENKUlvE0_clEv + 39
	18  MyApp               0x000000010bc421dd _ZNSt3__1L8__invokeIRZN13SettingsPanelC1EvEUlvE0_JEEEDTclclsr3std3__1E7forwardIT_Efp_Espclsr3std3__1E7forwardIT0_Efp0_EEEOS4_DpOS5_ + 29
	19  MyApp               0x000000010bc4218d _ZNSt3__128__invoke_void_return_wrapperIvLb1EE6__callIJRZN13SettingsPanelC1EvEUlvE0_EEEvDpOT_ + 29
	20  MyApp               0x000000010bc4215d _ZNSt3__110__function12__alloc_funcIZN13SettingsPanelC1EvEUlvE0_NS_9allocatorIS3_EEFvvEEclEv + 29
	21  MyApp               0x000000010bc40ea9 _ZNSt3__110__function6__funcIZN13SettingsPanelC1EvEUlvE0_NS_9allocatorIS3_EEFvvEEclEv + 25
	22  MyApp               0x000000010bc2bdc2 _ZNKSt3__110__function12__value_funcIFvvEEclEv + 50
	23  MyApp               0x000000010bc2bd45 _ZNKSt3__18functionIFvvEEclEv + 21
	24  MyApp               0x000000010c03e760 _ZN4juce6Button16sendClickMessageERKNS_12ModifierKeysE + 368
	25  MyApp               0x000000010c03ee66 _ZN4juce6Button21internalClickCallbackERKNS_12ModifierKeysE + 166
	26  MyApp               0x000000010c03f712 _ZN4juce6Button7mouseUpERKNS_10MouseEventE + 178
	27  MyApp               0x000000010c02b25c _ZN4juce9Component15internalMouseUpENS_16MouseInputSourceERKNS_12PointerStateENS_4TimeENS_12ModifierKeysE + 572
	28  MyApp               0x000000010c11a2b4 _ZN4juce24MouseInputSourceInternal11sendMouseUpERNS_9ComponentERKNS_12PointerStateENS_4TimeENS_12ModifierKeysE + 196
	29  MyApp               0x000000010c118a5e _ZN4juce24MouseInputSourceInternal10setButtonsERKNS_12PointerStateENS_4TimeENS_12ModifierKeysE + 414
	30  MyApp               0x000000010c031493 _ZN4juce24MouseInputSourceInternal11handleEventERNS_13ComponentPeerENS_5PointIfEENS_4TimeENS_12ModifierKeysEffNS_10PenDetailsE + 515
	31  MyApp               0x000000010c03127d _ZN4juce16MouseInputSource11handleEventERNS_13ComponentPeerENS_5PointIfEExNS_12ModifierKeysEffRKNS_10PenDetailsE + 173
	32  MyApp               0x000000010c0f414c _ZN4juce13ComponentPeer16handleMouseEventENS_16MouseInputSource15InputSourceTypeENS_5PointIfEENS_12ModifierKeysEffxNS_10PenDetailsEi + 204
	33  MyApp               0x000000010c1c311b _ZN4juce19NSViewComponentPeer14sendMouseEventEP7NSEvent + 171
	34  MyApp               0x000000010c1c3fe8 _ZN4juce19NSViewComponentPeer15redirectMouseUpEP7NSEvent + 88
	35  MyApp               0x000000010c1c2519 _ZN4juce15JuceNSViewClass11callOnOwnerIMNS_19NSViewComponentPeerEFvP7NSEventEJRS4_EEEvP11objc_objectOT_DpOT0_ + 153
	36  MyApp               0x000000010c1b6398 _ZN4juce15JuceNSViewClass12asyncMouseUpEP11objc_objectP13objc_selectorP7NSEvent + 56
	37  MyApp               0x000000010c1b6447 _ZN4juce15JuceNSViewClass7mouseUpEP11objc_objectP13objc_selectorP7NSEvent + 55
	38  AppKit              0x00007fff9adc7713 -[NSWindow _handleMouseUpEvent:isDelayedEvent:] + 119
	39  AppKit              0x00007fff9adc83ad -[NSWindow _reallySendEvent:isDelayedEvent:] + 212
	40  AppKit              0x00007fff9a807539 -[NSWindow sendEvent:] + 517
	41  AppKit              0x00007fff9a787a38 -[NSApplication sendEvent:] + 2540
	42  AppKit              0x00007fff9a5eedf2 -[NSApplication run] + 796
	43  MyApp               0x000000010bedc7a9 _ZN4juce14MessageManager15runDispatchLoopEv + 153
	44  MyApp               0x000000010bedc68f _ZN4juce19JUCEApplicationBase4mainEv + 399
	45  MyApp               0x000000010bedc49c _ZN4juce19JUCEApplicationBase4mainEiPPKc + 60
	46  MyApp               0x000000010bc7ce03 main + 51
	47  libdyld.dylib       0x00007fff936bb5ad start + 1
	48  ???                 0x0000000000000001 0x0 + 1
)

OK, I found the commit that broke the FileChooser when running a Sandboxed app on an older macOS (again, I’m testing on macOS 10.11):

I tested with the DialogsDemo before and after this commit. When Sandboxed, the app after the commit will not show an open or save dialog, and it throws the console error I mentioned above, that the panel “is not a supported subclass for sandboxing”.

Before this commit, the file chooser works fine in a sandboxed build. And, if the app is not sandboxed, then it works fine regardless.

@reuk is it possible to keep your custom panel implementations, and still have them subclass the appropriate classes that make sandboxing happy (NSSavePanel and NSOpenPanel, as I understand it)?

1 Like

Thanks for reporting, I’ve got a fix on the way.

1 Like

A fix is now available:

1 Like

Great, thank you. I’ll test it and let you know.

EDIT: It seems to have fixed the issue.

For those wanting to cherry pick the commit @reuk posted above, I’ll note that commit a9a95fe is also needed, so that SystemStats::isAppSandboxEnabled exists