Reputation: 9112
I have an untrusted app on macOS that I want to run, but without allowing it to connect to the internet.
What is the best way to achieve this?
My best idea was to build a simplistic launch app in swift in xcode, and sandbox this launcher. From what I read, apps launched from sandboxed apps should themselves be sandboxed.
So my launcher app looks like this:
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
@IBOutlet weak var window: NSWindow!
func applicationDidFinishLaunching(_ aNotification: Notification) {
NSWorkspace.shared.open("/path/inside/bundle/to/untrustedApp.app")
print ("after")
}
func applicationWillTerminate(_ aNotification: Notification) {
}
}
(Note that I used NSWorkspace.shared.open
because NSWorkspace.shared.openApp
didn't do anything, not even call the completion handler.)
And I added the sandbox capability in xcode, and made sure all boxes where unchecked. Am I doing anything wrong? Or is my understanding off?
Upvotes: 3
Views: 699
Reputation: 6180
One way is to use NSTask
to directly launch the Mach-O executable inside the untrusted app:
NSTask
inherits the sandbox of the parent app (See here)NSTask
lets you specify the Mach-O executable, which is necessary because untrusted.app
has it's own code signature, plist files, and entitlements (or lack thereof)For example, the following trivial application will get the name of the Mach-O executable from:
/path/to/your/ParentApp.app/relative/path/to/Restricted.app
For example, for firefox
:
/path/to/your/ParentApp.app/relative/path/to/Restricted.app/Contents/MacOS/firefox
Swift:
func applicationDidFinishLaunching(_ aNotification: Notification) {
let theMainAppBundle = Bundle.main.bundlePath
let theChildAppBundle = theMainAppBundle + ("/relative/path/to/RestrictedApp.app")
let childBundleExecutable = Bundle(path: theChildAppBundle)?.executablePath
Process.launchedProcess(launchPath: childBundleExecutable ?? "", arguments: [""])
NSApp.terminate(self)
}
Objective C:
(void)applicationDidFinishLaunching:(NSNotification *)aNotification {
NSString *theMainAppBundle = [[NSBundle mainBundle] bundlePath];
NSString *theChildAppBundle = [theMainAppBundle stringByAppendingString:@"/relative/path/to/RestrictedApp.app"];
NSString *childBundleExecutable = [NSBundle bundleWithPath:theChildAppBundle].executablePath;
[NSTask launchedTaskWithLaunchPath:childBundleExecutable arguments:[NSArray arrayWithObjects:@"", nil]];
[NSApp terminate:self];
}
Upvotes: 1