Sequel-ace: Un-sandboxed XPC Helper for Advanced Use-Cases

Created on 16 Sep 2020  路  18Comments  路  Source: Sequel-Ace/Sequel-Ace

Would it be possible to build an unsandboxed app during the GH release process?

The idea being that until and unless there is some what to allow socket connections there are a number of common-place use cases that are broken by the sandboxing process.

This is not to say that sandboxing is bad, but the decision of Sequel Ace to fully adopt sandboxing has broken a number of the 80% use cases, e.g. my company is among the growing number that require yubikey protected ssh keys, the common behavior of local mysql installations to use socket connections.

I'm not terribly familiar with the code changes required to sandbox an app so this might be an untenable proposition. However if the unsandboxing process is along the lines of removing an entitlement from the xcode project then I, among others would finally be able to use Sequel Ace.

Enhancement

Most helpful comment

I'll play around a bit this weekend. The docs make it seem like you can distribute an XPC as a way to break out of the sandbox if you need to.

All 18 comments

https://github.com/Sequel-Ace/Sequel-Ace/issues/201#issuecomment-658304147

I would rather not support both a sandboxed and non-sandboxed version of the app. I think it introduces a plethora of situations in the future where there is a bug in one version or the other and opens a big can of worms. You are welcome to [continue to] build your own non-sandboxed build, but I do not think we will build one or support one at this time.

I think the big issue is little differences that will emerge between the sandboxed and non-sandboxed versions of the app. As it is, we could really use more help on Sequel Ace and I'd be hesitant to add anything that would add further overhead to maintenance.

That's a reasonable position, I guess I'll just build it locally with sandboxing disabled. Is this something that could be revisited if no solution for sockets is forthcoming from Apple, (it's been several months鈥揳ny updates btw?)? I'm open to helping, but with sandboxing and without sockets Sequel Ace is DOA for me (and my coworkers which is why we're all still stuck using Sequel Pro)

Is this something that could be revisited if no solution for sockets is forthcoming from Apple

Certainly! What I'm really hoping we can figure out a way to do, although I haven't figured out a way to do it, would be to _not_ un-sandbox Sequel Ace, but to provide a helper that users can download and install that allows Sequel Ace additional access. So the main app just stays sandboxed/App Store/normal updates, but we have a separate helper that users who use sockets/yubikeys/other download and then, if present, Ace would use to connect to these resources.
What's tough, is it appears NSTasks share the sandbox they are launched from, which is how we launch the tunnel assistant. So I'm not really sure how to do it. If someone has an idea/can figure out how to make that work, I'm 100% for that.

Maybe an answer would be to create an XPC service? Apple Docs

Note: In rare cases, your app might have a small piece of functionality that cannot be sandboxed. Rather than abandon App Sandbox altogether, you might relegate the ineligible code to an XPC service that is not sandboxed. It is easier to secure a smaller piece of code than a larger one, and in this way, the bulk of your app enjoys the benefits of App Sandbox.

Do you know if this approach has been tried before? I'll do some more reading this weekend to see if we could use this.

Maybe an answer would be to create an XPC service? Apple Docs

Note: In rare cases, your app might have a small piece of functionality that cannot be sandboxed. Rather than abandon App Sandbox altogether, you might relegate the ineligible code to an XPC service that is not sandboxed. It is easier to secure a smaller piece of code than a larger one, and in this way, the bulk of your app enjoys the benefits of App Sandbox.

Do you know if this approach has been tried before? I'll do some more reading this weekend to see if we could use this.

I was looking into it, I haven't heard that anyone has tried it for Sequel Ace. The part I'm unclear about is if you can have XPC services accessible from your app outside of your app?

I'll play around a bit this weekend. The docs make it seem like you can distribute an XPC as a way to break out of the sandbox if you need to.

I put together a small demo (attached), that shows how XPC services can be used for reading files outside of the sandbox. I'm not entirely sure where to go from here, mostly because I don't have a great understanding of the SSH proxy architecture in SequelAce. I read the code but the lifecycle of all the bits is hard to follow. A couple questions occur:

  • Is it sufficient for the SSH command to have been run by an arbitrary process on the machine, or does it have to be run by the SequelAce process itself?
  • If the SSH command has to be executed by the process that talks to the DB, is it practicable or desirable to move all of the DB communications into an XPC that can be run outside the sandbox to still have access to sockets?
    (this would require an inter-process API but can also be a first step to making SequelAce DB agnostic鈥搃f that is a potential goal, e.g. a separate XPCs could host the MySql and SQLite code)

It's unclear from the archive documentation, but it may be the case that any XPC embedded in a MAS release needs to request a sandbox entitlement. If that is the case then the XPC approach can still work (there's a sandbox exception for talking to arbitrary XPC processes com.apple.security.temporary-exception.mach-lookup.global-name), but the helper XPC will have to be distributed as an ancillary download not in the MAS.

SandboxXPCTest.zip

WOW! Awesome, @clayreimann!

Currently the basic way it works (as I understand it, I inherited the setup) is an NSTask dispatches an ssh call and attaches the tunnel assistant as the SSH_ASKPASS target.
Once the tunnel is opened, the app pipes all traffic through the ns task and currently doesn't use the tunnel helper for actual communication.

It would be interesting if we could allow the app to continue to work as it does, but, if the XPC helper is present, utilize it. That way the app still works via App Store download (key to be approved) but can be _enhanced_ by installing the XPC helper. As to how the XPC helper actually gains access to files, that's going to be the complex part.

A good first thing to try to figure out would be if an XPC helper could gain access to a socket and somehow communicate that back to the main app to allow socket connections. I'm not familiar enough with XPCs capabilities to know how to go about that.

This issue has been marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

This issue has been auto-closed because there hasn't been any activity for at least 35 days. However, we really appreciate your contribution, so thank you for that! 馃檹 Also, feel free to open a new issue if you still experience this problem 馃憤.

@Sequel-Ace/all There was some good stuff here so flagging this so you all see it.
Notably, clearly some people have had success with the helper approach (https://community.codinn.com/t/core-helper/1103).

A good first thing to try to figure out would be if an XPC helper could gain access to a socket and somehow communicate that back to the main app to allow socket connections.

Tried @clayreimann project with

@Published var path = "/private/tmp/mysql.sock" {

But got

guard let bytes = FileManager.default.contents(atPath: path) else {
            return reply("Failed to get contents of '\(path)'")
        }

Might be I'm not using the project correctly...`

There you need to enable sandboxing for the main app and disable sandboxing for the XPC product. That simulates having 2 binaries, the MAS release and a manually installed XPC that lives outside the sandbox.

I'm currently figuring out how to talk over unix sockets using swift (because swift is more fun to write than Obj-C and I don't remember much Obj-C any more 馃槤). After that I need to figure out how to proxy the SSH_AUTH_SOCK traffic over the XPC transport and then back into the real (and external) SSH_AUTH_SOCK.

A little later this evening, I'll go ahead and publish my work so far over in https://github.com/Sequel-Ace/XPC-Playground. That'll be an easier way to collaborate on this.

More updates:

  • I found, forked, and cleaned up a unix socket library that I plan to use to do the proxying of SSH_AUTH_SOCK
  • I pushed my XPC playground project, and am working on integrating the aforementioned socket library to proxy the default ssh-agent's SSH_AUTH_SOCK

After that the things that still need figuring out

  • How to distribute a lone (and unsandboxed) XPC binary
  • How to surface the option to use this sandbox breaking XPC in the UI

More updates:

  • I found, forked, and cleaned up a unix socket library that I plan to use to do the proxying of SSH_AUTH_SOCK

  • I pushed my XPC playground project, and am working on integrating the aforementioned socket library to proxy the default ssh-agent's SSH_AUTH_SOCK

After that the things that still need figuring out

  • How to distribute a lone (and unsandboxed) XPC binary

  • How to surface the option to use this sandbox breaking XPC in the UI

Awesome!!!

Maybe I can chime in on the distribution and surfacing questions.

Distribution the simplest way would be to include a download link for the helper on GitHub? Perhaps it could be it's own separate repository with versioning/releases. Ideally the helper is simple enough that it really doesn't need to be updated frequently/ever. However, it may be a good idea to implement some sort of auto-update in case we do update it in the future? More thought here is needed likely. Perhaps the main app that interacts with the helper can check if the helper is installed; if the helper is installed but is an older version, then we could probably show a prompt in the app to update it. I don't think Apple would have an issue with us telling the user that their helper is outdated?

How to surface this option is hard. Basically I think we can't say anything about it in the app or Apple will be mad. I would say surfacing it we can reference it all over the documentation and GitHub? One thing we may be able to do is have a link on the connection failed error message that takes a user to the documentation. On that page we could explain common connection issues AND explain that the helper is needed for specific use cases (including a link to download and such).

Distribution the simplest way would be to include a download link for the helper on GitHub? Perhaps it could be it's own separate repository with versioning/releases.

This is what I was anticipating, what I meant is I'm not sure what sort of a thing we'll use. Is it just an installer that puts some magic .so file in a magic place. Do we build a full, unsandboxed, helper app that Sequel Ace talks to?

Basically I think we can't say anything about it in the app or Apple will be mad.

I'm not sure surfacing this directly to users will cause problems, based on the Core Sell FAQ you linked. This is what their app looks like:

image

So I think we're fine to have a similar checkbox down at the bottom of the connection page. This is, after all, a power user's app鈥搘e're not secreting a feature to get out of the sandbox to spy on users. This helper will enable legitimate use cases for (more) sophisticated users.

As to which to build, I would say whichever is easier and works well. Either way, really. I would prefer the helper tool/app is as small as possible, as minimal. But however it is, having an installer to put it in the right place is probably nice. TLDR if we can get away with a magic .so file, let's do that, unless it's a PITA.

Yup, honestly the best case may be to make it easy for power users and if apple rejects the app then tweak it. The one thing for sure is that the helper won't be able to be distributed through the App Store - users will have to go download it directly. Apple is very much not a fan of people breaking out of the sandbox, and most of our users probably won't ever need to install the helper. But for those who do need it, it definitely should be as easy as apple allows.

This issue has been marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

vuon9 picture vuon9  路  4Comments

SanderVanLeeuwen picture SanderVanLeeuwen  路  3Comments

ChrisGitIt picture ChrisGitIt  路  5Comments

nilbus picture nilbus  路  7Comments

robertoschwald picture robertoschwald  路  4Comments