macOS 13+: Is LOCAL_PEERTOKEN a supported way to authenticate AF_UNIX peers?

Hello,

I'm evaluating a local macOS helper service with a minimum deployment target of macOS 13.

The service would communicate over an AF_UNIX SOCK_STREAM socket and must authenticate the signed code identity of the connecting process before accepting an operation.

I'm investigating whether LOCAL_PEERTOKEN can provide a reliable audit token associated with the peer of an accepted socket.

The public macOS SDK declares LOCAL_PEERTOKEN in sys/un.h, but I haven't found documentation establishing its precise security guarantees or availability across supported macOS versions.

My questions are:

  1. Is LOCAL_PEERTOKEN a public, supported API on macOS 13 and later? Can it be used with getsockopt() on a file descriptor returned by accept() to retrieve an audit_token_t for the connected peer?

  2. At what point is the peer identity captured? Is the returned audit token securely bound to the original connecting process, even if that process exits and its PID is reused?

  3. Is the audit token obtained through LOCAL_PEERTOKEN officially supported as input to Security.framework APIs such as SecCodeCopyGuestWithAttributes (using kSecGuestAttributeAudit) or SecTaskCreateWithAuditToken?

  4. Does the identity remain trustworthy if the connected socket descriptor is inherited or passed to another process? Are there documented limitations concerning descriptor passing or time-of-check/time-of-use races?

  5. What is Apple's recommended public API sequence for verifying the signed code identity of an AF_UNIX peer on macOS 13+, including in an App Sandbox environment?

I'm looking for documented security and availability guarantees rather than relying solely on observed behavior.

Thank you!

Answered by DTS Engineer in 909406022
1- Is LOCAL_PEERTOKEN a public, supported API on macOS 13 and later?

Yes.

Can it be used with getsockopt() on a file descriptor returned by accept() to retrieve an audit_token_t for the connected peer?

Yes.

2- At what point is the peer identity captured?

When the peer connects.

even if that process exits and its PID is reused?

Protecting against PID reuse is one of the primary reasons that audit tokens exist.

3- Is the audit token obtained through LOCAL_PEERTOKEN officially supported as input to Security.framework APIs … ?

Yes. An audit token is an audit token. If you have one, you can use it wherever. There aren’t different flavours for use with different APIs.

4- Does the identity remain trustworthy if the connected socket descriptor is inherited or passed to another process?

No. But this is pretty much true of any Unix domain socket authentication scheme. You’d get exactly the same behaviour if, say, you rely on the file permissions to protect your listener. If someone connects, passes the file system check, and then passes the descriptor to another process that wouldn’t pass the file system check, there’s nothing you can do.

Having said that, I took a look at the code in xnu and it seems that somewhere along the line we made an effort to at least update this on the descriptor passing path.

5- What is Apple's recommended public API sequence for verifying the signed code identity of an AF_UNIX peer on macOS 13+ … ?

My recommendation is to use XPC rather than Unix domain sockets. XPC supports lots of nice features that Unix domain sockets don’t. And on the subject of authentication, XPC allows you to apply a code-signing requirement that the XPC subsystem checks for you.

Having said that, XPC does come with some limitations, most notably the lack of a good app-to-app (and child-to-parent) story.

I talk more about both of these in the resources linked to from XPC Resources.

Regardless, you can use the audit token and code signing path you outlined to do peer authentication with Unix domain sockets.

If your listener is sandboxed then you can run into problems if the client code’s executable is not accessible to you. You’ll likely find that your attempts to validate its signature fail with EPERM. This usually crops up during development. In production most clients are someone that’s available to your sandbox, for example, in the Applications folder.

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

1- Is LOCAL_PEERTOKEN a public, supported API on macOS 13 and later?

Yes.

Can it be used with getsockopt() on a file descriptor returned by accept() to retrieve an audit_token_t for the connected peer?

Yes.

2- At what point is the peer identity captured?

When the peer connects.

even if that process exits and its PID is reused?

Protecting against PID reuse is one of the primary reasons that audit tokens exist.

3- Is the audit token obtained through LOCAL_PEERTOKEN officially supported as input to Security.framework APIs … ?

Yes. An audit token is an audit token. If you have one, you can use it wherever. There aren’t different flavours for use with different APIs.

4- Does the identity remain trustworthy if the connected socket descriptor is inherited or passed to another process?

No. But this is pretty much true of any Unix domain socket authentication scheme. You’d get exactly the same behaviour if, say, you rely on the file permissions to protect your listener. If someone connects, passes the file system check, and then passes the descriptor to another process that wouldn’t pass the file system check, there’s nothing you can do.

Having said that, I took a look at the code in xnu and it seems that somewhere along the line we made an effort to at least update this on the descriptor passing path.

5- What is Apple's recommended public API sequence for verifying the signed code identity of an AF_UNIX peer on macOS 13+ … ?

My recommendation is to use XPC rather than Unix domain sockets. XPC supports lots of nice features that Unix domain sockets don’t. And on the subject of authentication, XPC allows you to apply a code-signing requirement that the XPC subsystem checks for you.

Having said that, XPC does come with some limitations, most notably the lack of a good app-to-app (and child-to-parent) story.

I talk more about both of these in the resources linked to from XPC Resources.

Regardless, you can use the audit token and code signing path you outlined to do peer authentication with Unix domain sockets.

If your listener is sandboxed then you can run into problems if the client code’s executable is not accessible to you. You’ll likely find that your attempts to validate its signature fail with EPERM. This usually crops up during development. In production most clients are someone that’s available to your sandbox, for example, in the Applications folder.

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

macOS 13+: Is LOCAL_PEERTOKEN a supported way to authenticate AF_UNIX peers?
 
 
Q