XPC is a a low-level (libSystem) interprocess communication mechanism that is based on serialized property lists.

Posts under XPC tag

200 Posts

Post

Replies

Boosts

Views

Activity

XPC Resources
XPC is the preferred inter-process communication (IPC) mechanism on Apple platforms. XPC has three APIs: The high-level NSXPCConnection API, for Objective-C and Swift The low-level Swift API, introduced with macOS 14 The low-level C API, which, while callable from all languages, works best with C-based languages General: Forums subtopic: App & System Services > Processes & Concurrency Forums tag: XPC Creating XPC services documentation NSXPCConnection class documentation Low-level API documentation XPC has extensive man pages — For the low-level API, start with the xpc man page; this is the original source for the XPC C API documentation and still contains titbits that you can’t find elsewhere. Also read the xpcservice.plist man page, which documents the property list format used by XPC services. Daemons and Services Programming Guide archived documentation WWDC 2012 Session 241 Cocoa Interprocess Communication with XPC — This is no longer available from the Apple Developer website )-: Technote 2083 Daemons and Agents — It hasn’t been updated in… well… decades, but it’s still remarkably relevant. TN3113 Testing and Debugging XPC Code With an Anonymous Listener technote XPC and App-to-App Communication forums post Validating Signature Of XPC Process forums post This forums post summarises the options for bidirectional communication This forums post explains the meaning of the privileged flag XPC is mostly used on macOS but there are a few places where it comes into play on iOS: File Provider extensions can export an XPC service to arbitrary apps. For more about the File Provider side of this, see the NSFileProviderServiceSource protocol. For more about the client side, see the NSFileProviderService class. An app can move part of its code into a helper extension and talk to it using XPC. See Creating enhanced security helper extensions. Alternative browser engines can do a similar thing. See BrowserEngineKit for more about this. Apps with embedded extensions can use XPC via ExtensionFoundation. (Note that on iOS, but not macOS, an app can only use extensions embedded within the app itself.) Related tags include: Inter-process communication, for other IPC mechanisms Service Management, for installing and uninstalling Service Management login items, launchd agents, and launchd daemons Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com"
0
0
4.5k
Mar ’26
Sandboxed SMAppService LaunchDaemon: supported identity and persistent storage?
Technology: Service Management (SMAppService), App Sandbox, launchd, Foundation file URLs. This is a documentation/support question based on a standalone signed probe. It is not an assertion of a confirmed Apple defect, and it is not a duplicate of the launchd enhancement FB24726121 referenced in DTS thread 844906. Request Please clarify the supported identity and persistent-storage architecture for this combination of requirements. We need a sandboxed Mac App Store app to install its bundled, sandboxed SMAppService LaunchDaemon through one in-app action and the required native approval. The LAN listener must be unprivileged and remain available after logout and at boot. On macOS 27.2 beta 1 (26B5086k), our signed app-like probe launches and accesses its private container as the default root identity. We have read DTS thread 844906’s single-process privilege-drop guidance; this request concerns the additional sandbox, storage, and distribution limits. Observations • UserName=nobody exits during sandbox initialization with /var/empty home and secinitd UID errors. • An existing non-root account control also traps in libsecinit before main. • SessionCreate=true with that existing non-root account still terminates in libsecinit before main. • Creating a new audit session did not resolve sandbox initialization in this probe. • A retained directory descriptor works with openat after dropping privileges, but ordinary container paths and /dev/fd/directory/child do not. • All diagnostic registrations were removed for these tests; no product data or network listener was involved. Questions Is a sandboxed bootstrap that permanently drops groups, GID, and UID before opening a LAN listener a supported architecture for the Mac App Store distribution lane? How should such a LaunchDaemon obtain an isolated service identity and persistent container with Foundation/MLX-compatible file URLs without an external installer, shared writable storage, manual account/ACL setup, or unsupported sandbox exceptions? Please identify the supported public-API path, and clearly distinguish Service Management support from App Review guideline 2.4.5 constraints. If these requirements cannot be combined, please state which ones are mutually exclusive. Reference: https://developer.apple.com/forums/thread/844906 Expected outcome: documented guidance on a supported arrangement, or a clear statement of which requirements cannot be combined. We are withholding the product’s Release host installation until the identity/storage design is qualified.
1
0
32
9h
Supported lifecycle and termination guarantees for an embedded macOS XPC service
We are evaluating a lifecycle architecture for a local macOS application and would appreciate guidance on supported public APIs. Proposed architecture: A normally signed, non-root host application. One embedded XPC service with exactly one intended client. No application-created subprocesses inside the service. No privileged helper, persistent LaunchAgent, exported endpoints, private APIs, or reduced system security. One bounded operation per session. Failed or interrupted operations must not automatically be retried. Initial validation would use synthetic workloads only. Our current evaluation target is macOS 15.6 on Apple silicon, using the macOS 15.5 SDK. Please identify any relevant deployment-version limitations. The XPC overview (https://developer.apple.com/documentation/xpc) describes an embedded service as tied to its client's lifetime. We also understand that xpc_connection_cancel (https://developer.apple.com/documentation/xpc/xpc_connection_cancel(_:)) is asynchronous and non-preemptive; we are not treating connection cancellation as proof of service termination. We need clarification on these points: Client death and service startup Does the documented client-lifetime relationship cover client termination, including SIGKILL, during service startup before the first reply? Does it also cover an already running service that is blocked or stopped with SIGSTOP? Which behavior is guaranteed, and which timing or failure cases are intentionally unspecified? Timeout while the client remains alive What supported public mechanism should a normal application use to terminate its own unresponsive embedded service when an operation exceeds its deadline? We want to avoid PID enumeration, PID-reuse races, broad process-group signaling, and exporting a full task-control port. Is there a supported identity-bound termination mechanism? If not, what architecture does Apple recommend? A stopped or hung client remains alive, so we do not assume client-lifetime coupling handles that separate failure case. Observing termination Which public notification reliably identifies the exit of the particular service instance, as distinct from connection invalidation or a missing reply? Because launchd is the parent, the application cannot simply waitpid the service. Is reaping entirely launchd's responsibility, and what completion claim can the application legitimately make? Identity and required privileges Which public signing requirements, launch constraints, sandbox settings, or entitlements are necessary for this architecture? Please distinguish authentication before accepting work from constraints enforced before service code executes. We do not assume peer authentication also grants termination rights. Restart behavior After interruption, cancellation, client exit, or service failure, under what circumstances can launchd or subsequent XPC activity start a replacement service? What supported pattern prevents accidental resubmission or resumption of the same failed operation? We are not asking for hard real-time guarantees during kernel failure, or claiming that forced termination proves callback completion or explicit memory zeroization. If this combination of requirements is unsupported, identifying that boundary and the smallest supported architectural alternative would be a useful answer. Documentation references or a minimal public sample would be welcome.
1
0
53
20h
ManagedAppConfigurationProvider fails with XPC 4099 in Location Push Service Extension
I am developing an iOS application with a Location Push Service Extension and am trying to provide managed app configuration to the extension using Apple's ManagedAppConfigurationProvider and Declarative Device Management (DDM). The same managed configuration works correctly in the containing application, but the exact same API fails when called from the Location Push Service Extension. Environment: iOS: 26.2.1 Xcode: 16.4 Extension type: Location Push Service Extension The extension has the following entitlement in both the signed extension and provisioning profile: com.apple.developer.location.push The extension is configured through DDM using ExtensionConfigs: "ExtensionConfigs": { "bundleid (teamid)": { "DataAssetReference": "xxxxxxx" } } The Data Asset is successfully compiled by the MDM server and contains the managed configuration values. The device reports the following DDM status: "config-state": { "app-config-state": { "state": "valid" }, "extension-config-state": { "bundleidofextension": { "state": "unknown" } } } The main application can successfully retrieve the configuration using: let provider = ManagedAppConfigurationProvider() Task { for await configuration in await provider.configurations( ModelManagedAppConfiguration.self ) { print("APP CONFIG = (String(describing: configuration))") } } The same code and the same configuration type are used inside the Location Push Service Extension. Inside the extension, the provider is created successfully: LOCATION EXTENSION: creating ManagedAppConfigurationProvider LOCATION EXTENSION: provider created LOCATION EXTENSION: requesting configurations However, the request fails with: Failed to connect to managedappsd with error Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.apple.devicemanagementclient.managedappsd was invalidated from this process." Failed to fetch managed app configuration. Returning nil. Error: XPC connection failed with error Optional("Couldn’t communicate with a helper application.") Failed to determine managed app configuration changed notification name. Unable to register for notifications. Failed to report configuration error state. Error: XPC connection failed with error Optional("Couldn’t communicate with a helper application.") LOCATION EXTENSION: CONFIG = nil The important observation is that the configuration works from the containing application but fails from the Location Push Service Extension before the configuration reaches the Decodable configuration type. I have also verified: The extension Bundle ID matches the ExtensionConfigs entry. The Team ID matches. com.apple.developer.location.push is present in the signed extension. com.apple.developer.location.push is also present in the provisioning profile. The DDM Data Asset is successfully compiled. The containing application's managed configuration state is valid. The same ManagedAppConfigurationProvider code works in the containing application. According to Apple's documentation, ManagedAppConfigurationProvider provides configurations for a managed app or extension, and ExtensionConfigs is the DDM mechanism for configuring extensions. My question is: Is ManagedAppConfigurationProvider fully supported from a Location Push Service Extension? If it is supported, what could cause managedappsd to reject/invalidate the XPC connection specifically when the request originates from a Location Push Service Extension? Could there be an additional entitlement, extension-specific configuration, or system restriction required for ManagedAppConfigurationProvider to communicate with managedappsd from this type of extension? Any guidance on how to further diagnose the NSCocoaErrorDomain Code=4099 / "Couldn’t communicate with a helper application" error would be appreciated.
5
0
646
2d
Is suspended spawn + audit_token_t matching a supported security boundary for one exact macOS process occurrence?
I’m designing a macOS privileged-service boundary and I’d like to clarify whether a process-occurrence authentication pattern previously described by Apple DTS is a supported shipping security contract, rather than just behaviour that happens to work on current macOS. Target: current macOS 26.x, using public APIs only. Threat model An arbitrary hostile process may run as the same ordinary, non-admin login user as the application. The attacker can launch an exact second copy of the legitimately signed requester binary. The attacker cannot obtain administrator / Touch ID authorization and does not control root, SIP, Recovery, the kernel, or the code-signing infrastructure. Desired property After a fresh Human-authorized operation, a root LaunchDaemon should grant authority to one specific requester process occurrence, not to every process having the same code-signing identity. Apple DTS thread 842442 describes a pattern based on: launching the requester suspended with posix_spawn(..., POSIX_SPAWN_START_SUSPENDED); obtaining a name/task port for that process; reading its TASK_AUDIT_TOKEN; resuming the process; and accepting only Mach messages whose kernel audit trailer identifies that same process occurrence. Thread 842442 also describes this area as being on “thin compatibility ice”, which is why I do not want to build a security boundary on behaviour that Apple does not intend applications to rely on. My core question is: Can a shipping macOS application rely on a pre-bound audit_token_t obtained from a suspended child and compare it against the audit token in subsequent raw Mach message trailers as a supported security boundary for that exact process occurrence? In particular, I need to know whether the supported contract covers: distinguishing another process with the exact same signed executable; PID reuse after the original process exits; messages queued before or around sender termination; a Mach send right transferred to another process — does the receiver see the audit token of the process that actually sends each message?; later exec by the original process; and whether full audit_token_t equality is an appropriate supported comparison for this purpose. If that is not a supported shipping contract, is there a current public XPC API that provides the equivalent property: binding one privileged-service session to one exact process occurrence rather than merely to its code-signing identity? I’m specifically trying to distinguish: code identity = this is an approved executable from mission authority = this one particular authorized process occurrence I’m happy with a negative answer if macOS does not expose a stable public contract for the latter. Related Apple DTS discussion: https://developer.apple.com/forums/thread/842442
11
0
590
5d
AlarmKit alarms fire late (or not until you wake up the iPhone)
Hey all, I've submitted a couple Feedback reports on this (FB22887867 on iOS 26 and FB24483266 on iOS 27), but wanted to share here for 1. validation that I'm not the only one experiencing this issue and 2. ask for ideas or experience with potential workarounds. The issue is that AlarmKit alarms, even when properly configured and scheduled from an app, will intermittently fire late, or not fire at all until the iPhone is woken up. For example, you might create an AlarmKit alarm with a relative schedule for 6:00am, then lock your iPhone before bed. When 6:00am passes, nothing happens. Then, at 6:13am it fires (with the full screen alert, audio and haptics) Or, you might wake up at 6:53am, notice that it didn't fire, tap the screen on your iPhone, the Lock Screen displays for about a second, then all of a sudden, the AlarmKit alert presents (with the full screen alert, audio and haptics). The issue has been present from iOS 26.0 up through the iOS 27.0 RC. I'm fairly confident that this is not a configuration issue. I've reproduced it using the WWDC 25 AlarmKit sample code and if you read from AlarmManager.shared.alarms, these alarms show up as expected: with a scheduled state and the correct times. The issue seems to be more common overnight, when the iPhone has been asleep for a while. It's less common on my personal iPhone but occurs probably once out of every 3 to 5 alarms on my test iPhones (which have much less interaction and background activity etc.). Of our app's few thousand daily users, we get complaints at least once a day. I've dropped a few sysdiagnose reports into Claude. In every instance, it claims that when the alarm was scheduled, mobiletimerd successfully registered an XPC wake-up for the alarm. However, during a completely unrelated event overnight (ex: a wifi packet), launchd drops the scheduled wake-up and nothing re-schedules it. So when 6:00am rolls around, nothing wakes up the iPhone to let the alarm fire. On days when it fires late, it's simply because another unrelated event (ex: a wifi packet) woke up the iPhone while the late alarm was queued. Looking forward to hearing your thoughts. Thank you.
1
0
147
1w
SMAppService LaunchDaemon: is privilege drop followed by same-PID exec supported before Mach service check-in?
I’m designing a least-privilege system LaunchDaemon registered with SMAppService, and I’d like to clarify whether the following architecture is supported by public macOS contracts. The LaunchDaemon declares a MachServices entry. Its steady-state service must run as a dedicated non-root account and later creates an NSXPCListener for that Mach service. We currently launch the daemon directly using UserName, GroupName, and InitGroups=false. However, InitGroups=false does not appear to guarantee that the resulting process supplementary-group list is limited to the service’s intended group. In testing, the daemon received a supplementary group outside our accepted set. We therefore do not want to depend on incidental inherited launch-time group state. We are considering this alternative: launchd starts a small, fixed, code-signed bootstrap executable as root. The bootstrap reads the target UID/GID from an existing protected root-owned binding record. It establishes an exact credential state using public BSD APIs, conceptually: setgroups(...) setgid(...) setuid(...) It verifies the resulting non-root credentials. It creates no XPC listener or storage connection while privileged. Without forking, it permanently replaces itself using execve() (or possibly POSIX_SPAWN_SETEXEC) with another fixed, separately signed executable in the same bundle. That non-root executable independently validates its security state and then creates NSXPCListener(machServiceName:) for the Mach service declared by the original LaunchDaemon job. The bootstrap would not remain as a privileged parent or supervisor. My main questions are: Is a same-PID exec after permanent UID/GID/supplementary-group reduction supported for an SMAppService system LaunchDaemon before it checks in to its declared Mach service? Does the exec-replaced process retain the launchd/bootstrap context required for NSXPCListener(machServiceName:) to check in to that Mach service? If so, what execution context must be preserved across exec (for example bootstrap context, environment, file descriptors, or Mach rights)? Is there a documented way to preserve only the context required for the LaunchDaemon/Mach-service relationship without carrying unintended root-derived capabilities into the non-root executable? Would SMAppService.unregister() / normal launchd termination continue to treat the exec-replaced process as the same LaunchDaemon job? If this topology is not supported, is there an Apple-supported way to establish an exact supplementary-group set before a non-root SMAppService LaunchDaemon begins handling its Mach service? The goal is to avoid relying on undocumented launchd behavior, incidental supplementary groups, private APIs, or a long-lived privileged helper. I’m specifically looking for the supported contract here rather than whether this happens to work on a particular macOS release.
4
0
325
1w
Supported public API to prebind a macOS process occurrence and match a later XPC or Mach sender
I’m looking for clarification on supported public API semantics on macOS. Target runtime: arm64 macOS 15.4.1 build 24E263 The question is whether macOS provides a supported public API, or a supported composition of public APIs, that allows an external launcher or OS observer to: Obtain and freeze an identifier I(P) for the exact post-exec occurrence of a process P before P sends a security-sensitive IPC request. Later obtain OS-supplied sender identity J(M) for an individual XPC or raw Mach message M. Determine, using documented comparison semantics, whether J(M) identifies the same process-image occurrence as I(P). The comparison needs to distinguish cases such as: two concurrent processes with the same UID and signed code; exec replacement while retaining a PID; exit, restart, and PID reuse; stale or queued messages; a transferred XPC endpoint or Mach send right; an undelegated proxy. PID, UID, code-signing identity, launch labels, connection/right possession, or “first message wins” are not sufficient by themselves for this requirement. I have looked at mechanisms including: suspended process launch; task identity tokens; Endpoint Security AUTH_EXEC process identity; XPC per-message sender identity; SecCodeCreateWithXPCMessage; Mach audit trailers. What I have not found is public documentation defining a common process-occurrence identity and a supported comparison procedure across the pre-IPC and later message-sender surfaces. A token generated by the target and sent in its first message also would not solve this specific problem, because the process claiming the token has already selected itself before the external observer binds the expected occurrence. Is there a supported public way to achieve this? If so, I would appreciate pointers to: the relevant public APIs; the canonical comparison procedure; required entitlements, task rights, TCC permissions, root privileges, or system-extension requirements; documented behavior across exec, exit, restart, and PID reuse; relevant Apple documentation or sample code. If there is no supported public API that provides this property, confirmation of that would also be very helpful. I’m specifically interested in documented, supported public API semantics rather than private SPI or undocumented implementation behavior.
2
0
771
Aug ’26
TelephonyMessagingKit drops first SMS at cold launch — race between client XPC handler registration and server pending flush
Hi all, I'm the developer of OV Message, an end-to-end encrypted SMS messaging app already shipped on Google Play (Android, where it natively encrypts SMS content). The iOS port aims to be the default carrier-messaging app, handling SMS, MMS, and RCS through TelephonyMessagingKit with the com.apple.developer.carrier-messaging-app entitlement under the EU programme. While testing the cold-launch flow on iOS 26.x, I've hit a reproducible bug that silently drops the first SMS/MMS/RCS that wakes the app, and I'd like to confirm whether other devs working with this API see the same. The bug When a default carrier-messaging app is force-killed and a message arrives, iOS correctly: Routes the message via CommCenter (IMS in my case — SFR France) Wakes the app in background (state = .background at didFinishLaunchingWithOptions) Acquires a TelephonyMessaging runningboard assertion on the app But CommCenter then pushes the pending message via XPC before the client TMK library has finished registering its messageHandlersByID dictionary. Result: client responds Received unhandled request, server logs TMKXPCError Code=2, message is dropped, never delivered to for await in incomingMessageNotifications. Subsequent messages (with the app warm) work fine. Native log sequence (from idevicesyslog with the Telephony logging profile) T+0.000 CommCenter: SMS arrives via IMS (k3GPP) T+0.003 CommCenter: Default app is set to com.example.app T+0.004 CommCenter: Attempting to launch and acquire process assertion T+0.083 CommCenter: Notifying SMS message received, target: bundleID=... T+0.085 CommCenter(TMK): There are no client connections matching, pending message [~125 ms — app boots] T+0.128 App(TMK): Configuring connection T+0.128 App(TMK): Pinging remote end T+0.130 CommCenter(TMK): Received new connection from PID T+0.130 CommCenter(TMK): New incoming connection, flushing pending messages (1) ← server flushes T+0.130 App(TMK): Received unhandled request ← client not ready T+0.131 CommCenter(TMK): Failed to send pending message: TMKXPCError Code=2 T+0.132 App(TMK): Registered for IncomingMessageNotification (smsReceived) ← ~2 ms too late The race window between Pinging remote end (client) and Registered for IncomingMessageNotification (client) is 2–7 ms across my measurements. CommCenter considers the connection ready as soon as the ping completes, but the client library populates messageHandlersByID slightly after, so the dispatch fails. Minimal reproduction I built a ~50-line Swift app to confirm this isn't specific to OV Message. UIKit AppDelegate, single for await in TelephonyMessagingSession.shared.smsService.incomingMessageNotifications started in didFinishLaunchingWithOptions. No SwiftUI, no other modules, no Darwin notifications. Just TMK. Steps: Build & install on iPhone iOS 26.x with carrier-messaging-app entitlement (auto-provisioned in iOS 26) Settings → Apps → Default Messaging → select the test app Force-kill, then send 2 SMS in rapid succession from another phone Wait 30 s, open the app — log shows only the 2nd SMS Same result: the 1st SMS is gone. I've reproduced this consistently dozens of times. Source code (Swift + xcodegen project.yml): https://gist.github.com/ovmessage/fbc529292a65222191bec6ce5e5a4275 What I've tried Task.detached(priority: .userInitiated) to decouple the for await from main thread scheduling — no effect (race is internal to TMK lib, before our scheduling) Pre-fetching cellularServices synchronously — no effect Subscribing MMS + RCS in parallel — no effect Direct XPCSession/xpc_connection_create_mach_service to com.apple.commcenter.tmk.xpc — Apple has marked these unavailable on iOS for 3rd-party apps (no public way to bypass the lib) I've also done runtime introspection of the TMK framework via Mirror, which confirms the architecture: a single XPCConnection.messageHandlersByID dict shared by smsReceived, mmsReceived, rcsReceivedNotification — all four entries (incl. serviceStatusNotification) are populated after the XPC ping. So the same race affects SMS, MMS, and RCS equally. Suggested fixes (Apple-side) Either: Server (CommCenter): defer flushing pending messages until the client confirms its handlers are registered (extra XPC handshake message) Client (TelephonyMessagingKit): register messageHandlersByID entries before sending Pinging remote end, so they exist when the server starts flushing Buffer client-side: cache messages received before handler registration completes, dispatch on attach Filed in Feedback Assistant FB[YOUR_FB_NUMBER_HERE] Question for fellow devs If you're also building with carrier-messaging-app entitlement (Beeper, Google Messages on iOS, anyone in the EU programme), can you confirm whether you see the same race? Especially interested in whether: It happens with non-IMS carriers (mine is SFR France, IMS-routed via SIP) iOS 26.1 / 26.2 changed the timing Anyone has found a workaround I haven't tried Thanks.
7
1
1.4k
Jul ’26
Validating Signature Of XPC Process
Quinn, you've often suggested that to validate the other side of an XPC connection, we should use the audit token. But that's not available from the XPC object, whereas the PID is. So everyone uses the PID. While looking for something completely unrelated, I found this in the SecCode.h file OSStatus SecCodeCreateWithXPCMessage(xpc_object_t message, SecCSFlags flags, SecCodeRef * __nonnull CF_RETURNS_RETAINED target); Would this be the preferred way to do this now? At least from 11.0 and up. Like I said, I was looking for something completely unrelated and found this and don't have the cycles right now to try it. But it looks promising from the description and I wanted to check in with you about it in case you can say yes or no before I get a chance to test it. Thanks
8
0
9.1k
Jul ’26
Outgoing XPC message goes through to untrusted Peer
I have run into an interesting topic today. So far, I have been under the impression that when I am using the setCodeSigningRequirement() function on an NSXPCConnection, I am completely removing any chance of receiving AND sending messages to untrusted XPC Peers. However, I created a malicious replacement for my daemon, and I wanted to check if my application can still send and receive messages to it. I checked with codesign --verify that the replacement does NOT fulfil the code signing requirement. I put a system log instruction in the malicious tool's XPC function. When calling the XPC Peer, I expected to see: XPC connection to <redacted> failed! [Error Domain=NSCocoaErrorDomain Code=4102 "The code signature requirement failed." UserInfo={NSDebugDescription=The code signature requirement failed.}] and I did. However, I also saw the system log from the malicious tool's XPC function. Then, I checked all XPC documentation, and I found for the original C implementation - xpc_connection_set_peer_code_signing_requirement() - the following in the discussion section: All messages received on this connection will be checked to ensure they come from a peer who satisfies the code signing requirement. For a listener connection, requests that do not satisfy the requirement are dropped. When a reply is expected on the connection and the peer does not satisfy the requirement XPC_ERROR_PEER_CODE_SIGNING_REQUIREMENT will be delivered instead of the reply. (this is in xpc/connection.h) which seems to align with the observed results. However, this is (embarassingly?) new for me, I would have never expected this, given how in my head pre-checking before any connection is made seems straightforward, even with public Apple SDK APIs: Grab a SecCode (not SecStaticCode) object of the daemon (malicious or not). This is running code, so it cannot be substituted between the check and the outgoing message. Perform validations on the SecCode object in some form - on macOS 15.0+ it's pretty easy with LightweightCodeRequirement's SecCodeCheckValidityWithProcessRequirement(). Immediately drop the connection if the peer is untrusted, before any message is sent. Am I overlooking something or making wrong assumptions here? or Am I right and this is something that I have to accept that's implemented less than ideally and I can perform above steps 1-3 myself and make a difference? Thanks in advance!
1
1
1.2k
Jul ’26
XPC connection consistently invalidated on app upgrade
Hi, Our project is a MacOS SwiftUI GUI application that bundles a System Network Extension, signed with a Developer ID certificate for distribution outside of the app store. The system network extension is used to write a packet tunnel provider. The signing of the app & network extension is handled by XCode (v16.0.0), we do not run codesign ourselves. We have no issues with XPC or the system network extension during normal usage, nor when the application is installed on a user's device for the first time. The problem only arises when the user upgrades the application. I have experienced this issue myself, as have our users. It's been reported on Apple Silicon macbooks running at least macOS 15.3.2. Much like the SimpleFirewall example (which we used as a reference), we use XPC for basic communication of state between the app and NE. These XPC connections stop working when the user installs a new version of the app, with OS logs from the process indicating that the connection is immediately invalidated. Subsequent connection attempts are also immediately invalidated. Toggling the VPN in system settings (or via the app) does not resolve the problem, nor does restarting the app, nor does deleting and reinstalling the app, nor does restarting the device. The only reliable workaround is to delete the system extension in Login Items & Extensions, under Network Extensions. No device restart is necessary to garbage collect the old extension - once the extension is reapproved by the user, the XPC issue resolves itself. This would be an acceptable workaround were it possible to automate the deleting of the system extension, but that appears deliberately not possible, and requiring our users to do this each time they update is unreasonable. When the upgraded app is opened for the first time, the OSSystemExtensionRequest request is sent, and the outcome is that the previously installed system network extension is replaced, as both the CFBundleVersion and CFBundleShortVersionString differ. When this issue is encountered, the output of systemextensionsctl list shows the later version is installed and activated. I've been able to reproduce this bug on my personal laptop, with SIP on and systemextensionsctl developer off, but on my work laptop with SIP off and systemextensionsctl developer on (where the network extension is replaced on each activation request, instead of only when the version strings differ), I do not encounter this issue, which leads me to believe it has something to do with the notarization process. We notarize the pkg using xcrun notarytool, and then staple to the pkg. This is actually the same issue described in: https://developer.apple.com/forums/thread/711713 https://developer.apple.com/forums/thread/667597 https://developer.apple.com/forums/thread/742992 https://developer.apple.com/forums/thread/728063 but it's been a while since any of these threads were updated, and we've made attempts to address it off the suggestions in the threads to no avail. Those suggestions are: Switching to a .pkg installer from a .dmg As part of the .pkg preinstall, doing all of the following: Stopping the VPN (scutil --nc stop), shutting down the app (using osascript 'quit app id'), and deleting the app (which claims to delete the network extension, but not the approval in Login Items & Extensions remains??), by running rm -rf on the bundle in /Applications As part of the .pkg postinstall: Forcing macOS to ingest the App bundle's notarization ticket using spctl --assess. Ensuring NSXPCListener.resume() is called after autoreleasepool { NEProvider.startSystemExtensionMode() } (mentioned in a forum thread above as a fix, did not help.) One thing I'm particularly interested in is the outcome of this feedback assistant ticket, as I can't view it: FB11086599. It was shared on this forum in the first thread above, and supposedly describes the same issue. I almost find it hard to believe that this issue has been around for this many years without a workaround (there's system network extension apps out there that appear to work fine when updating, are they not using XPC?), so I wonder if there's a fix described in that FB ticket. Since I can't view that above feedback ticket, I've created my own: FB17032197
8
0
1.9k
Jun ’26
Sandboxed App <> Launch Agent - how to communicate?
I’m building a sandboxed macOS App Store app that registers an agent using SMAppService. I’m trying to understand the IPC setup between the main app and the SMAppService-managed agent. The obvious options seem to be: XPC with a Mach service But from what I understand, I’d need a special entitlement that allows me to communicate over XPC Mach service - which is unlikely to pass Mac App Store review. So how do people communicate with processes registered with SMAppService?
2
0
1.1k
Jun ’26
Can SMAppService Daemon replace SMJobBless for exclusive HID capture from keyboards?
To gain exclusive access to keyboard HID devices like Amazon Fire Bluetooth remote controls, my app has been installing a privileged helper tool with SMJobBless in the past. The app - which also has Accessibility permissions - then invoked and communicated with that helper tool through XPC. Now I'm looking into replacing that with a daemon installed through the newer SMAppService APIs, but running into a permission problem: If I try to exclusively open a keyboard HID device from the SMAppService-registered XPC service/daemon (which runs as root as seen in Activity Monitor), IOHIDDeviceOpen returns kIOReturnNotPermitted. I've spent many hours now trying to get it to work, but so far didn't find a solution. Could it be that XPC services registered as a daemon through SMAppService do not inherit the TCC permissions from the invoking process (here: Accessibility permissions) - and the exclusive IOHIDDeviceOpen therefore fails?
9
0
987
Jun ’26
XPC can't activate after app upgrade
I have an app with a system network extension. After app upgrade some customers experience broken XPC that they fix by restarting the computer. The app cannot recover by re-launching the tunnel or retrying xpc after 3 seconds. I do OSSystemExtensionRequest.activationRequest on app start and actionForReplacingExtension has .replace. I haven't experienced this before and I don't think I've changed anything, so perhaps macOS 26 has changed xpc handling. Current fix proposal is to deactivate&activate the sysext when vpn is connected, but xpc fails to connect. It's better than computer restart, but it's still not a nice user experience, because user action is required to reenable the sysext. Do you have better ideas? The system logs below show failed xpc connection after upgrade 2026-05-21 12:09:43.017192-0700 0x5b640 Default 0x0 1 0 launchd: [system:] service inactive: NetworkExtension.com.company.macos.stg.tunnelprovider.2026.124.124909 2026-05-21 12:09:43.132350-0700 0x5b7f5 Default 0x0 1 0 launchd: [system/NetworkExtension.com.company.macos.stg.tunnelprovider.2026.124.124909 [78132]:] Successfully spawned com.company.macos.stg.tunnelprovider[78132] because xpc event 2026-05-21 12:09:43.192084-0700 0x5bd02 Default 0x0 78132 0 com.company.macos.stg.tunnelprovider: (libxpc.dylib) [com.apple.xpc:connection] [0x103b01f70] activating connection: mach=true listener=true peer=false name=6GX8KVTR9H.com.company.stg.service 2026-05-21 12:09:43.195957-0700 0x5b640 Default 0x0 1 0 launchd: [system:] failed lookup: name = com.apple.pasteboard.1, requestor = com.company.ma[78132], error = 3: No such process 2026-05-21 12:09:43.246588-0700 0x5b640 Default 0x0 1 0 launchd: [system:] failed lookup: name = com.apple.securityd.xpc, requestor = com.company.ma[78132], error = 3: No such process 2026-05-21 12:09:43.994210-0700 0x5b47a Default 0x0 1 0 launchd: [gui/501 [100025]:] service inactive: application.com.company.macos.stg.155106945.155106951 2026-05-21 12:09:43.996937-0700 0x5b47a Default 0x0 1 0 launchd: [gui/501 [100025]:] removing service: application.com.company.macos.stg.155106945.155106951 2026-05-21 12:09:50.175890-0700 0x5be9d Default 0x0 78205 0 Company Stg: (libxpc.dylib) [com.apple.xpc:connection] [0xc32c92080] activating connection: mach=true listener=false peer=false name=com.company.macos.stg-spks 2026-05-21 12:09:50.175937-0700 0x5b7f5 Default 0x0 1 0 launchd: [gui/501 [100025]:] failed lookup: name = com.company.macos.stg-spks, requestor = Company Stg[78205], error = 3: No such process 2026-05-21 12:09:50.602809-0700 0x5b7f5 Default 0x0 1 0 launchd: [system/NetworkExtension.com.company.macos.stg.tunnelprovider.2026.140.125099:] The endpoint "6GX8KVTR9H.com.company.stg.service" defined in plist already exists and is owned by: NetworkExtension.com.company.macos.stg.tunnelprovider.2026.124.124909 2026-05-21 12:09:50.605301-0700 0x5b7f5 Default 0x0 1 0 launchd: [system:] service inactive: NetworkExtension.com.company.macos.stg.tunnelprovider.2026.124.124909 2026-05-21 12:09:50.605302-0700 0x5b7f5 Default 0x0 1 0 launchd: [system:] removing service: NetworkExtension.com.company.macos.stg.tunnelprovider.2026.124.124909 2026-05-21 12:09:50.662682-0700 0x5b47a Default 0x0 1 0 launchd: [system/NetworkExtension.com.company.macos.stg.tunnelprovider.2026.140.125099 [78238]:] Successfully spawned com.company.macos.stg.tunnelprovider[78238] because xpc event 2026-05-21 12:09:52.396190-0700 0x5bfd6 Default 0x0 78238 0 com.company.macos.stg.tunnelprovider: (libxpc.dylib) [com.apple.xpc:connection] [0x103839c60] activating connection: mach=true listener=true peer=false name=6GX8KVTR9H.com.company.stg.service 2026-05-21 12:09:52.396217-0700 0x5bfcf Default 0x0 1 0 launchd: [system:] failed activation: name = 6GX8KVTR9H.com.company.stg.service, flags = 0x0, requestor = com.company.ma[78238], error = 1: Operation not permitted 2026-05-21 12:09:52.399064-0700 0x5b47a Default 0x0 1 0 launchd: [system:] failed lookup: name = com.apple.pasteboard.1, requestor = com.company.ma[78238], error = 3: No such process 2026-05-21 12:09:52.450706-0700 0x5bfcf Default 0x0 1 0 launchd: [system:] failed lookup: name = com.apple.securityd.xpc, requestor = com.company.ma[78238], error = 3: No such process 2026-05-21 12:09:52.607836-0700 0x5be9d Default 0x0 78205 0 Company Stg: (libxpc.dylib) [com.apple.xpc:connection] [0xc3295d7c0] activating connection: mach=true listener=false peer=false name=6GX8KVTR9H.com.company.stg.service 2026-05-21 12:09:52.607964-0700 0x5b47a Default 0x0 1 0 launchd: [system:] failed lookup: name = 6GX8KVTR9H.com.company.stg.service, flags = 0x8, requestor = Company Stg[78205], error = 3: No such process 2026-05-21 12:09:55.610528-0700 0x5be9d Default 0x0 78205 0 Company Stg: (libxpc.dylib) [com.apple.xpc:connection] [0xc3295de00] activating connection: mach=true listener=false peer=false name=6GX8KVTR9H.com.company.stg.service 2026-05-21 12:09:55.610694-0700 0x5b47a Default 0x0 1 0 launchd: [system:] failed lookup: name = 6GX8KVTR9H.com.company.stg.service, flags = 0x8, requestor = Company Stg[78205], error = 3: No such process
2
0
751
May ’26
XPC Communication between Editor app and user-compiled code
Hello! I'm trying to implement an editor app (macOS) that allows the user to write code, which will be compiled and executed, showing the result in the editor window. Imagine it like SwiftUI previews, but the graphic output is created with Metal, not SwiftUI. I found that IOSurface can be used to share that kind of data over XPC, so I would not have to rely on the private NSRemoteView. However, I'm confused if it is, at all, possible for my editor app to connect to an XPC Service, that was NOT bundled with it (but compiled by it at runtime). I succeeded to launch an XPC service defined as: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.myteam.myproject.service</string> <key>MachServices</key> <dict> <key>com.myteam.myproject.service</key> <true/> </dict> <key>Program</key> <string>/Path/to/service/run_my_service.sh</string> </dict> </plist> But the call to let connection = NSXPCConnection(machServiceName: "com.myteam.myproject.service") let proxy = connection.remoteObjectProxyWithErrorHandler { error in continuation.resume(throwing: error) } as? MyServiceProtocol fails with "The connection to service named com.myteam.myproject.service was invalidated: Connection init failed at lookup with error 3 - No such process." I have added <key>com.apple.security.temporary-exception.mach-lookup.global-name</key> <array> <string>com.myteam.myproject.service</string> </array> to my entitlements. Since the tutorials I followed are quite old, I'm wondering if support for something like this was dropped at some point. Thanks for any advice!
6
0
1.7k
May ’26
How much practical benefit is there to XPC-based privilege separation?
"Privilege separation" is one of the "two main reasons to use XPC services" given by https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingXPCServices.html — With traditional applications, if an application becomes compromised through a buffer overflow or other security vulnerability, the attacker gains the ability to do anything that the user can do. To mitigate this risk, Mac OS X provides sandboxing—limiting what types of operations a process can perform. […] Each XPC service has its own sandbox, so XPC services can make it easier to implement proper privilege separation. The idea (iiuc) being that if the main process is compromised, the spicier operations have been separated out to a separate process space, and this improves the security of the system. But if the main process is compromised, and that main process is trusted by the more-privileged XPC service, is not the system still compromised in practice? That is rather than the exploit being: exploit some vulnerability gain arbitrary code execution do something naughty isn't the same still possible with just one extra step: exploit vulnerability arbitrary execution ask the XPC service nicely… …to do something naughty?
3
0
454
May ’26
XPC connection broken on app & extension upgrade
Post app update our extension version is replaced with the new version. However occasionally maybe around 20% of the time The XPC connection we have for communication between the app and extension will not work. We have reconnection retry logic as well as tried stop and starting the extension but it appears once its broken its broken and all that fixes it is a machine restart. This is obviously not ideal. I have noticed a few other forums talking about the same or similar problem. https://developer.apple.com/forums/thread/728063 https://developer.apple.com/forums/thread/779395 https://developer.apple.com/forums/thread/742992 When we run on a broken upgrade cycle `sudo launchctl print system/NetworkExtension.com.company.example.app.filter.5.5.0.2248 ` We notice that endpoints is missing from the log. However if we run the same command in terminal for a working upgrade cycle endpoints = {} exist. Therefore for some reason our xpc isn't actually getting registered.
1
0
892
May ’26
XPC connection broken on app & extension upgrade
After an app update replaces our extension with the new version, the XPC connection between the app and the extension fails to work roughly 20% of the time. Once it's broken, it stays broken — our reconnect/retry logic doesn't recover it, stopping and starting the extension doesn't recover it, and the only thing that fixes it is a full machine restart. This obviously isn't ideal. I've seen a few other threads describing the same or a very similar issue: https://developer.apple.com/forums/thread/728063 https://developer.apple.com/forums/thread/779395 https://developer.apple.com/forums/thread/742992 On a broken upgrade cycle, when we run: sudo launchctl print system/NetworkExtension.com.company.example.app.filter.5.5.0.2248 the endpoints entry is missing from the output entirely. On a working upgrade cycle, the same command shows endpoints = {} is present. So it looks like our XPC service isn't actually getting registered with launchd in the broken case. We've tried various changes to our connection logic, but nothing prevents the issue — random upgrades still end up broken with no obvious cause. Is there a known way to recover the XPC registration without requiring a machine restart?
1
0
879
May ’26
XPC doesn't work with network extension on app upgrade
Our app has a network extension (as I've mentioned lots 😄). We do an upgrade by downloading the new package, stopping & removing all of our components except for the network extension, and then installing the new package, which then loads a LaunchAgent causing the containing app to run. (The only difference between a new install and upgrade is the old extension is left running, but not having anything to tell it what to do, just logs and continues.) On some (but not all) upgrades... nothing ends up able to communicate via XPC with the Network Extension. My simplest cli program to talk to it gets Could not create proxy: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named blah was invalidated: failed at lookup with error 3 - No such process." UserInfo={NSDebugDescription=The connection to service named bla was invalidated: failed at lookup with error 3 - No such process.} Could not communicate with blah Restarting the extension by doing a kill -9 doesn't fix it; neither does restarting the control daemon. The only solution we've come across so far is rebooting. I filed FB11086599 about this, but has anyone thoughts about this?
20
2
5.3k
May ’26
How to debug a Launch Daemon that requires an App Group provisioning profile for XPC communication
Hello, I am developing a macOS Launch Daemon (packaged as a bundle) that acts as an XPC server. For debugging purposes, I am trying to run the daemon's executable directly from the terminal via sudo ./mydaemon.app/Contents/MacOS/myexecutable. Initially, I added the com.apple.security.application-groups entitlement to the daemon. However, when starting the process, it failed to create the XPC service with the following errors: Unsatisfied entitlements: com.apple.security.application-groups Soft-restriction provisioning profile validation failure: Error Domain=AppleMobileFileIntegrityError Code=-413 "No matching profile found" UserInfo={NSURL=, unsatisfiedEntitlements=, NSLocalizedDescription=No matching profile found} listener failed to activate: xpc_error=[1: Operation not permitted] To resolve the profile validation failure, I registered a new App Group in the Apple Developer Portal, generated a new provisioning profile for the daemon that includes this group, and embedded it into the bundle (Contents/embedded.provisionprofile). Now, the previous profile error is gone, but I am getting a new identity conflict error, and the XPC listener still fails: Two equal instances have unequal identities. <anon<myproc_name>(501) pid=2818 AUID=501> and <anon<myproc_name>(501)(262) pid=2818 AUID=262> listener failed to activate: xpc_error=[1: Operation not permitted] My questions are: What exactly causes the Two equal instances have unequal identities error? I noticed the Audit UID difference (AUID=501 vs AUID=262). Why does NSXPCListener still fail with Operation not permitted? What is the recommended workflow for debugging a Launch Daemon that requires an App Group provisioning profile for XPC communication? Thank you in advance!
2
0
1.2k
Apr ’26
XPC Resources
XPC is the preferred inter-process communication (IPC) mechanism on Apple platforms. XPC has three APIs: The high-level NSXPCConnection API, for Objective-C and Swift The low-level Swift API, introduced with macOS 14 The low-level C API, which, while callable from all languages, works best with C-based languages General: Forums subtopic: App & System Services > Processes & Concurrency Forums tag: XPC Creating XPC services documentation NSXPCConnection class documentation Low-level API documentation XPC has extensive man pages — For the low-level API, start with the xpc man page; this is the original source for the XPC C API documentation and still contains titbits that you can’t find elsewhere. Also read the xpcservice.plist man page, which documents the property list format used by XPC services. Daemons and Services Programming Guide archived documentation WWDC 2012 Session 241 Cocoa Interprocess Communication with XPC — This is no longer available from the Apple Developer website )-: Technote 2083 Daemons and Agents — It hasn’t been updated in… well… decades, but it’s still remarkably relevant. TN3113 Testing and Debugging XPC Code With an Anonymous Listener technote XPC and App-to-App Communication forums post Validating Signature Of XPC Process forums post This forums post summarises the options for bidirectional communication This forums post explains the meaning of the privileged flag XPC is mostly used on macOS but there are a few places where it comes into play on iOS: File Provider extensions can export an XPC service to arbitrary apps. For more about the File Provider side of this, see the NSFileProviderServiceSource protocol. For more about the client side, see the NSFileProviderService class. An app can move part of its code into a helper extension and talk to it using XPC. See Creating enhanced security helper extensions. Alternative browser engines can do a similar thing. See BrowserEngineKit for more about this. Apps with embedded extensions can use XPC via ExtensionFoundation. (Note that on iOS, but not macOS, an app can only use extensions embedded within the app itself.) Related tags include: Inter-process communication, for other IPC mechanisms Service Management, for installing and uninstalling Service Management login items, launchd agents, and launchd daemons Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com"
Replies
0
Boosts
0
Views
4.5k
Activity
Mar ’26
Sandboxed SMAppService LaunchDaemon: supported identity and persistent storage?
Technology: Service Management (SMAppService), App Sandbox, launchd, Foundation file URLs. This is a documentation/support question based on a standalone signed probe. It is not an assertion of a confirmed Apple defect, and it is not a duplicate of the launchd enhancement FB24726121 referenced in DTS thread 844906. Request Please clarify the supported identity and persistent-storage architecture for this combination of requirements. We need a sandboxed Mac App Store app to install its bundled, sandboxed SMAppService LaunchDaemon through one in-app action and the required native approval. The LAN listener must be unprivileged and remain available after logout and at boot. On macOS 27.2 beta 1 (26B5086k), our signed app-like probe launches and accesses its private container as the default root identity. We have read DTS thread 844906’s single-process privilege-drop guidance; this request concerns the additional sandbox, storage, and distribution limits. Observations • UserName=nobody exits during sandbox initialization with /var/empty home and secinitd UID errors. • An existing non-root account control also traps in libsecinit before main. • SessionCreate=true with that existing non-root account still terminates in libsecinit before main. • Creating a new audit session did not resolve sandbox initialization in this probe. • A retained directory descriptor works with openat after dropping privileges, but ordinary container paths and /dev/fd/directory/child do not. • All diagnostic registrations were removed for these tests; no product data or network listener was involved. Questions Is a sandboxed bootstrap that permanently drops groups, GID, and UID before opening a LAN listener a supported architecture for the Mac App Store distribution lane? How should such a LaunchDaemon obtain an isolated service identity and persistent container with Foundation/MLX-compatible file URLs without an external installer, shared writable storage, manual account/ACL setup, or unsupported sandbox exceptions? Please identify the supported public-API path, and clearly distinguish Service Management support from App Review guideline 2.4.5 constraints. If these requirements cannot be combined, please state which ones are mutually exclusive. Reference: https://developer.apple.com/forums/thread/844906 Expected outcome: documented guidance on a supported arrangement, or a clear statement of which requirements cannot be combined. We are withholding the product’s Release host installation until the identity/storage design is qualified.
Replies
1
Boosts
0
Views
32
Activity
9h
Supported lifecycle and termination guarantees for an embedded macOS XPC service
We are evaluating a lifecycle architecture for a local macOS application and would appreciate guidance on supported public APIs. Proposed architecture: A normally signed, non-root host application. One embedded XPC service with exactly one intended client. No application-created subprocesses inside the service. No privileged helper, persistent LaunchAgent, exported endpoints, private APIs, or reduced system security. One bounded operation per session. Failed or interrupted operations must not automatically be retried. Initial validation would use synthetic workloads only. Our current evaluation target is macOS 15.6 on Apple silicon, using the macOS 15.5 SDK. Please identify any relevant deployment-version limitations. The XPC overview (https://developer.apple.com/documentation/xpc) describes an embedded service as tied to its client's lifetime. We also understand that xpc_connection_cancel (https://developer.apple.com/documentation/xpc/xpc_connection_cancel(_:)) is asynchronous and non-preemptive; we are not treating connection cancellation as proof of service termination. We need clarification on these points: Client death and service startup Does the documented client-lifetime relationship cover client termination, including SIGKILL, during service startup before the first reply? Does it also cover an already running service that is blocked or stopped with SIGSTOP? Which behavior is guaranteed, and which timing or failure cases are intentionally unspecified? Timeout while the client remains alive What supported public mechanism should a normal application use to terminate its own unresponsive embedded service when an operation exceeds its deadline? We want to avoid PID enumeration, PID-reuse races, broad process-group signaling, and exporting a full task-control port. Is there a supported identity-bound termination mechanism? If not, what architecture does Apple recommend? A stopped or hung client remains alive, so we do not assume client-lifetime coupling handles that separate failure case. Observing termination Which public notification reliably identifies the exit of the particular service instance, as distinct from connection invalidation or a missing reply? Because launchd is the parent, the application cannot simply waitpid the service. Is reaping entirely launchd's responsibility, and what completion claim can the application legitimately make? Identity and required privileges Which public signing requirements, launch constraints, sandbox settings, or entitlements are necessary for this architecture? Please distinguish authentication before accepting work from constraints enforced before service code executes. We do not assume peer authentication also grants termination rights. Restart behavior After interruption, cancellation, client exit, or service failure, under what circumstances can launchd or subsequent XPC activity start a replacement service? What supported pattern prevents accidental resubmission or resumption of the same failed operation? We are not asking for hard real-time guarantees during kernel failure, or claiming that forced termination proves callback completion or explicit memory zeroization. If this combination of requirements is unsupported, identifying that boundary and the smallest supported architectural alternative would be a useful answer. Documentation references or a minimal public sample would be welcome.
Replies
1
Boosts
0
Views
53
Activity
20h
ManagedAppConfigurationProvider fails with XPC 4099 in Location Push Service Extension
I am developing an iOS application with a Location Push Service Extension and am trying to provide managed app configuration to the extension using Apple's ManagedAppConfigurationProvider and Declarative Device Management (DDM). The same managed configuration works correctly in the containing application, but the exact same API fails when called from the Location Push Service Extension. Environment: iOS: 26.2.1 Xcode: 16.4 Extension type: Location Push Service Extension The extension has the following entitlement in both the signed extension and provisioning profile: com.apple.developer.location.push The extension is configured through DDM using ExtensionConfigs: "ExtensionConfigs": { "bundleid (teamid)": { "DataAssetReference": "xxxxxxx" } } The Data Asset is successfully compiled by the MDM server and contains the managed configuration values. The device reports the following DDM status: "config-state": { "app-config-state": { "state": "valid" }, "extension-config-state": { "bundleidofextension": { "state": "unknown" } } } The main application can successfully retrieve the configuration using: let provider = ManagedAppConfigurationProvider() Task { for await configuration in await provider.configurations( ModelManagedAppConfiguration.self ) { print("APP CONFIG = (String(describing: configuration))") } } The same code and the same configuration type are used inside the Location Push Service Extension. Inside the extension, the provider is created successfully: LOCATION EXTENSION: creating ManagedAppConfigurationProvider LOCATION EXTENSION: provider created LOCATION EXTENSION: requesting configurations However, the request fails with: Failed to connect to managedappsd with error Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.apple.devicemanagementclient.managedappsd was invalidated from this process." Failed to fetch managed app configuration. Returning nil. Error: XPC connection failed with error Optional("Couldn’t communicate with a helper application.") Failed to determine managed app configuration changed notification name. Unable to register for notifications. Failed to report configuration error state. Error: XPC connection failed with error Optional("Couldn’t communicate with a helper application.") LOCATION EXTENSION: CONFIG = nil The important observation is that the configuration works from the containing application but fails from the Location Push Service Extension before the configuration reaches the Decodable configuration type. I have also verified: The extension Bundle ID matches the ExtensionConfigs entry. The Team ID matches. com.apple.developer.location.push is present in the signed extension. com.apple.developer.location.push is also present in the provisioning profile. The DDM Data Asset is successfully compiled. The containing application's managed configuration state is valid. The same ManagedAppConfigurationProvider code works in the containing application. According to Apple's documentation, ManagedAppConfigurationProvider provides configurations for a managed app or extension, and ExtensionConfigs is the DDM mechanism for configuring extensions. My question is: Is ManagedAppConfigurationProvider fully supported from a Location Push Service Extension? If it is supported, what could cause managedappsd to reject/invalidate the XPC connection specifically when the request originates from a Location Push Service Extension? Could there be an additional entitlement, extension-specific configuration, or system restriction required for ManagedAppConfigurationProvider to communicate with managedappsd from this type of extension? Any guidance on how to further diagnose the NSCocoaErrorDomain Code=4099 / "Couldn’t communicate with a helper application" error would be appreciated.
Replies
5
Boosts
0
Views
646
Activity
2d
Is suspended spawn + audit_token_t matching a supported security boundary for one exact macOS process occurrence?
I’m designing a macOS privileged-service boundary and I’d like to clarify whether a process-occurrence authentication pattern previously described by Apple DTS is a supported shipping security contract, rather than just behaviour that happens to work on current macOS. Target: current macOS 26.x, using public APIs only. Threat model An arbitrary hostile process may run as the same ordinary, non-admin login user as the application. The attacker can launch an exact second copy of the legitimately signed requester binary. The attacker cannot obtain administrator / Touch ID authorization and does not control root, SIP, Recovery, the kernel, or the code-signing infrastructure. Desired property After a fresh Human-authorized operation, a root LaunchDaemon should grant authority to one specific requester process occurrence, not to every process having the same code-signing identity. Apple DTS thread 842442 describes a pattern based on: launching the requester suspended with posix_spawn(..., POSIX_SPAWN_START_SUSPENDED); obtaining a name/task port for that process; reading its TASK_AUDIT_TOKEN; resuming the process; and accepting only Mach messages whose kernel audit trailer identifies that same process occurrence. Thread 842442 also describes this area as being on “thin compatibility ice”, which is why I do not want to build a security boundary on behaviour that Apple does not intend applications to rely on. My core question is: Can a shipping macOS application rely on a pre-bound audit_token_t obtained from a suspended child and compare it against the audit token in subsequent raw Mach message trailers as a supported security boundary for that exact process occurrence? In particular, I need to know whether the supported contract covers: distinguishing another process with the exact same signed executable; PID reuse after the original process exits; messages queued before or around sender termination; a Mach send right transferred to another process — does the receiver see the audit token of the process that actually sends each message?; later exec by the original process; and whether full audit_token_t equality is an appropriate supported comparison for this purpose. If that is not a supported shipping contract, is there a current public XPC API that provides the equivalent property: binding one privileged-service session to one exact process occurrence rather than merely to its code-signing identity? I’m specifically trying to distinguish: code identity = this is an approved executable from mission authority = this one particular authorized process occurrence I’m happy with a negative answer if macOS does not expose a stable public contract for the latter. Related Apple DTS discussion: https://developer.apple.com/forums/thread/842442
Replies
11
Boosts
0
Views
590
Activity
5d
AlarmKit alarms fire late (or not until you wake up the iPhone)
Hey all, I've submitted a couple Feedback reports on this (FB22887867 on iOS 26 and FB24483266 on iOS 27), but wanted to share here for 1. validation that I'm not the only one experiencing this issue and 2. ask for ideas or experience with potential workarounds. The issue is that AlarmKit alarms, even when properly configured and scheduled from an app, will intermittently fire late, or not fire at all until the iPhone is woken up. For example, you might create an AlarmKit alarm with a relative schedule for 6:00am, then lock your iPhone before bed. When 6:00am passes, nothing happens. Then, at 6:13am it fires (with the full screen alert, audio and haptics) Or, you might wake up at 6:53am, notice that it didn't fire, tap the screen on your iPhone, the Lock Screen displays for about a second, then all of a sudden, the AlarmKit alert presents (with the full screen alert, audio and haptics). The issue has been present from iOS 26.0 up through the iOS 27.0 RC. I'm fairly confident that this is not a configuration issue. I've reproduced it using the WWDC 25 AlarmKit sample code and if you read from AlarmManager.shared.alarms, these alarms show up as expected: with a scheduled state and the correct times. The issue seems to be more common overnight, when the iPhone has been asleep for a while. It's less common on my personal iPhone but occurs probably once out of every 3 to 5 alarms on my test iPhones (which have much less interaction and background activity etc.). Of our app's few thousand daily users, we get complaints at least once a day. I've dropped a few sysdiagnose reports into Claude. In every instance, it claims that when the alarm was scheduled, mobiletimerd successfully registered an XPC wake-up for the alarm. However, during a completely unrelated event overnight (ex: a wifi packet), launchd drops the scheduled wake-up and nothing re-schedules it. So when 6:00am rolls around, nothing wakes up the iPhone to let the alarm fire. On days when it fires late, it's simply because another unrelated event (ex: a wifi packet) woke up the iPhone while the late alarm was queued. Looking forward to hearing your thoughts. Thank you.
Replies
1
Boosts
0
Views
147
Activity
1w
SMAppService LaunchDaemon: is privilege drop followed by same-PID exec supported before Mach service check-in?
I’m designing a least-privilege system LaunchDaemon registered with SMAppService, and I’d like to clarify whether the following architecture is supported by public macOS contracts. The LaunchDaemon declares a MachServices entry. Its steady-state service must run as a dedicated non-root account and later creates an NSXPCListener for that Mach service. We currently launch the daemon directly using UserName, GroupName, and InitGroups=false. However, InitGroups=false does not appear to guarantee that the resulting process supplementary-group list is limited to the service’s intended group. In testing, the daemon received a supplementary group outside our accepted set. We therefore do not want to depend on incidental inherited launch-time group state. We are considering this alternative: launchd starts a small, fixed, code-signed bootstrap executable as root. The bootstrap reads the target UID/GID from an existing protected root-owned binding record. It establishes an exact credential state using public BSD APIs, conceptually: setgroups(...) setgid(...) setuid(...) It verifies the resulting non-root credentials. It creates no XPC listener or storage connection while privileged. Without forking, it permanently replaces itself using execve() (or possibly POSIX_SPAWN_SETEXEC) with another fixed, separately signed executable in the same bundle. That non-root executable independently validates its security state and then creates NSXPCListener(machServiceName:) for the Mach service declared by the original LaunchDaemon job. The bootstrap would not remain as a privileged parent or supervisor. My main questions are: Is a same-PID exec after permanent UID/GID/supplementary-group reduction supported for an SMAppService system LaunchDaemon before it checks in to its declared Mach service? Does the exec-replaced process retain the launchd/bootstrap context required for NSXPCListener(machServiceName:) to check in to that Mach service? If so, what execution context must be preserved across exec (for example bootstrap context, environment, file descriptors, or Mach rights)? Is there a documented way to preserve only the context required for the LaunchDaemon/Mach-service relationship without carrying unintended root-derived capabilities into the non-root executable? Would SMAppService.unregister() / normal launchd termination continue to treat the exec-replaced process as the same LaunchDaemon job? If this topology is not supported, is there an Apple-supported way to establish an exact supplementary-group set before a non-root SMAppService LaunchDaemon begins handling its Mach service? The goal is to avoid relying on undocumented launchd behavior, incidental supplementary groups, private APIs, or a long-lived privileged helper. I’m specifically looking for the supported contract here rather than whether this happens to work on a particular macOS release.
Replies
4
Boosts
0
Views
325
Activity
1w
Supported public API to prebind a macOS process occurrence and match a later XPC or Mach sender
I’m looking for clarification on supported public API semantics on macOS. Target runtime: arm64 macOS 15.4.1 build 24E263 The question is whether macOS provides a supported public API, or a supported composition of public APIs, that allows an external launcher or OS observer to: Obtain and freeze an identifier I(P) for the exact post-exec occurrence of a process P before P sends a security-sensitive IPC request. Later obtain OS-supplied sender identity J(M) for an individual XPC or raw Mach message M. Determine, using documented comparison semantics, whether J(M) identifies the same process-image occurrence as I(P). The comparison needs to distinguish cases such as: two concurrent processes with the same UID and signed code; exec replacement while retaining a PID; exit, restart, and PID reuse; stale or queued messages; a transferred XPC endpoint or Mach send right; an undelegated proxy. PID, UID, code-signing identity, launch labels, connection/right possession, or “first message wins” are not sufficient by themselves for this requirement. I have looked at mechanisms including: suspended process launch; task identity tokens; Endpoint Security AUTH_EXEC process identity; XPC per-message sender identity; SecCodeCreateWithXPCMessage; Mach audit trailers. What I have not found is public documentation defining a common process-occurrence identity and a supported comparison procedure across the pre-IPC and later message-sender surfaces. A token generated by the target and sent in its first message also would not solve this specific problem, because the process claiming the token has already selected itself before the external observer binds the expected occurrence. Is there a supported public way to achieve this? If so, I would appreciate pointers to: the relevant public APIs; the canonical comparison procedure; required entitlements, task rights, TCC permissions, root privileges, or system-extension requirements; documented behavior across exec, exit, restart, and PID reuse; relevant Apple documentation or sample code. If there is no supported public API that provides this property, confirmation of that would also be very helpful. I’m specifically interested in documented, supported public API semantics rather than private SPI or undocumented implementation behavior.
Replies
2
Boosts
0
Views
771
Activity
Aug ’26
TelephonyMessagingKit drops first SMS at cold launch — race between client XPC handler registration and server pending flush
Hi all, I'm the developer of OV Message, an end-to-end encrypted SMS messaging app already shipped on Google Play (Android, where it natively encrypts SMS content). The iOS port aims to be the default carrier-messaging app, handling SMS, MMS, and RCS through TelephonyMessagingKit with the com.apple.developer.carrier-messaging-app entitlement under the EU programme. While testing the cold-launch flow on iOS 26.x, I've hit a reproducible bug that silently drops the first SMS/MMS/RCS that wakes the app, and I'd like to confirm whether other devs working with this API see the same. The bug When a default carrier-messaging app is force-killed and a message arrives, iOS correctly: Routes the message via CommCenter (IMS in my case — SFR France) Wakes the app in background (state = .background at didFinishLaunchingWithOptions) Acquires a TelephonyMessaging runningboard assertion on the app But CommCenter then pushes the pending message via XPC before the client TMK library has finished registering its messageHandlersByID dictionary. Result: client responds Received unhandled request, server logs TMKXPCError Code=2, message is dropped, never delivered to for await in incomingMessageNotifications. Subsequent messages (with the app warm) work fine. Native log sequence (from idevicesyslog with the Telephony logging profile) T+0.000 CommCenter: SMS arrives via IMS (k3GPP) T+0.003 CommCenter: Default app is set to com.example.app T+0.004 CommCenter: Attempting to launch and acquire process assertion T+0.083 CommCenter: Notifying SMS message received, target: bundleID=... T+0.085 CommCenter(TMK): There are no client connections matching, pending message [~125 ms — app boots] T+0.128 App(TMK): Configuring connection T+0.128 App(TMK): Pinging remote end T+0.130 CommCenter(TMK): Received new connection from PID T+0.130 CommCenter(TMK): New incoming connection, flushing pending messages (1) ← server flushes T+0.130 App(TMK): Received unhandled request ← client not ready T+0.131 CommCenter(TMK): Failed to send pending message: TMKXPCError Code=2 T+0.132 App(TMK): Registered for IncomingMessageNotification (smsReceived) ← ~2 ms too late The race window between Pinging remote end (client) and Registered for IncomingMessageNotification (client) is 2–7 ms across my measurements. CommCenter considers the connection ready as soon as the ping completes, but the client library populates messageHandlersByID slightly after, so the dispatch fails. Minimal reproduction I built a ~50-line Swift app to confirm this isn't specific to OV Message. UIKit AppDelegate, single for await in TelephonyMessagingSession.shared.smsService.incomingMessageNotifications started in didFinishLaunchingWithOptions. No SwiftUI, no other modules, no Darwin notifications. Just TMK. Steps: Build & install on iPhone iOS 26.x with carrier-messaging-app entitlement (auto-provisioned in iOS 26) Settings → Apps → Default Messaging → select the test app Force-kill, then send 2 SMS in rapid succession from another phone Wait 30 s, open the app — log shows only the 2nd SMS Same result: the 1st SMS is gone. I've reproduced this consistently dozens of times. Source code (Swift + xcodegen project.yml): https://gist.github.com/ovmessage/fbc529292a65222191bec6ce5e5a4275 What I've tried Task.detached(priority: .userInitiated) to decouple the for await from main thread scheduling — no effect (race is internal to TMK lib, before our scheduling) Pre-fetching cellularServices synchronously — no effect Subscribing MMS + RCS in parallel — no effect Direct XPCSession/xpc_connection_create_mach_service to com.apple.commcenter.tmk.xpc — Apple has marked these unavailable on iOS for 3rd-party apps (no public way to bypass the lib) I've also done runtime introspection of the TMK framework via Mirror, which confirms the architecture: a single XPCConnection.messageHandlersByID dict shared by smsReceived, mmsReceived, rcsReceivedNotification — all four entries (incl. serviceStatusNotification) are populated after the XPC ping. So the same race affects SMS, MMS, and RCS equally. Suggested fixes (Apple-side) Either: Server (CommCenter): defer flushing pending messages until the client confirms its handlers are registered (extra XPC handshake message) Client (TelephonyMessagingKit): register messageHandlersByID entries before sending Pinging remote end, so they exist when the server starts flushing Buffer client-side: cache messages received before handler registration completes, dispatch on attach Filed in Feedback Assistant FB[YOUR_FB_NUMBER_HERE] Question for fellow devs If you're also building with carrier-messaging-app entitlement (Beeper, Google Messages on iOS, anyone in the EU programme), can you confirm whether you see the same race? Especially interested in whether: It happens with non-IMS carriers (mine is SFR France, IMS-routed via SIP) iOS 26.1 / 26.2 changed the timing Anyone has found a workaround I haven't tried Thanks.
Replies
7
Boosts
1
Views
1.4k
Activity
Jul ’26
Validating Signature Of XPC Process
Quinn, you've often suggested that to validate the other side of an XPC connection, we should use the audit token. But that's not available from the XPC object, whereas the PID is. So everyone uses the PID. While looking for something completely unrelated, I found this in the SecCode.h file OSStatus SecCodeCreateWithXPCMessage(xpc_object_t message, SecCSFlags flags, SecCodeRef * __nonnull CF_RETURNS_RETAINED target); Would this be the preferred way to do this now? At least from 11.0 and up. Like I said, I was looking for something completely unrelated and found this and don't have the cycles right now to try it. But it looks promising from the description and I wanted to check in with you about it in case you can say yes or no before I get a chance to test it. Thanks
Replies
8
Boosts
0
Views
9.1k
Activity
Jul ’26
Outgoing XPC message goes through to untrusted Peer
I have run into an interesting topic today. So far, I have been under the impression that when I am using the setCodeSigningRequirement() function on an NSXPCConnection, I am completely removing any chance of receiving AND sending messages to untrusted XPC Peers. However, I created a malicious replacement for my daemon, and I wanted to check if my application can still send and receive messages to it. I checked with codesign --verify that the replacement does NOT fulfil the code signing requirement. I put a system log instruction in the malicious tool's XPC function. When calling the XPC Peer, I expected to see: XPC connection to <redacted> failed! [Error Domain=NSCocoaErrorDomain Code=4102 "The code signature requirement failed." UserInfo={NSDebugDescription=The code signature requirement failed.}] and I did. However, I also saw the system log from the malicious tool's XPC function. Then, I checked all XPC documentation, and I found for the original C implementation - xpc_connection_set_peer_code_signing_requirement() - the following in the discussion section: All messages received on this connection will be checked to ensure they come from a peer who satisfies the code signing requirement. For a listener connection, requests that do not satisfy the requirement are dropped. When a reply is expected on the connection and the peer does not satisfy the requirement XPC_ERROR_PEER_CODE_SIGNING_REQUIREMENT will be delivered instead of the reply. (this is in xpc/connection.h) which seems to align with the observed results. However, this is (embarassingly?) new for me, I would have never expected this, given how in my head pre-checking before any connection is made seems straightforward, even with public Apple SDK APIs: Grab a SecCode (not SecStaticCode) object of the daemon (malicious or not). This is running code, so it cannot be substituted between the check and the outgoing message. Perform validations on the SecCode object in some form - on macOS 15.0+ it's pretty easy with LightweightCodeRequirement's SecCodeCheckValidityWithProcessRequirement(). Immediately drop the connection if the peer is untrusted, before any message is sent. Am I overlooking something or making wrong assumptions here? or Am I right and this is something that I have to accept that's implemented less than ideally and I can perform above steps 1-3 myself and make a difference? Thanks in advance!
Replies
1
Boosts
1
Views
1.2k
Activity
Jul ’26
XPC connection consistently invalidated on app upgrade
Hi, Our project is a MacOS SwiftUI GUI application that bundles a System Network Extension, signed with a Developer ID certificate for distribution outside of the app store. The system network extension is used to write a packet tunnel provider. The signing of the app & network extension is handled by XCode (v16.0.0), we do not run codesign ourselves. We have no issues with XPC or the system network extension during normal usage, nor when the application is installed on a user's device for the first time. The problem only arises when the user upgrades the application. I have experienced this issue myself, as have our users. It's been reported on Apple Silicon macbooks running at least macOS 15.3.2. Much like the SimpleFirewall example (which we used as a reference), we use XPC for basic communication of state between the app and NE. These XPC connections stop working when the user installs a new version of the app, with OS logs from the process indicating that the connection is immediately invalidated. Subsequent connection attempts are also immediately invalidated. Toggling the VPN in system settings (or via the app) does not resolve the problem, nor does restarting the app, nor does deleting and reinstalling the app, nor does restarting the device. The only reliable workaround is to delete the system extension in Login Items & Extensions, under Network Extensions. No device restart is necessary to garbage collect the old extension - once the extension is reapproved by the user, the XPC issue resolves itself. This would be an acceptable workaround were it possible to automate the deleting of the system extension, but that appears deliberately not possible, and requiring our users to do this each time they update is unreasonable. When the upgraded app is opened for the first time, the OSSystemExtensionRequest request is sent, and the outcome is that the previously installed system network extension is replaced, as both the CFBundleVersion and CFBundleShortVersionString differ. When this issue is encountered, the output of systemextensionsctl list shows the later version is installed and activated. I've been able to reproduce this bug on my personal laptop, with SIP on and systemextensionsctl developer off, but on my work laptop with SIP off and systemextensionsctl developer on (where the network extension is replaced on each activation request, instead of only when the version strings differ), I do not encounter this issue, which leads me to believe it has something to do with the notarization process. We notarize the pkg using xcrun notarytool, and then staple to the pkg. This is actually the same issue described in: https://developer.apple.com/forums/thread/711713 https://developer.apple.com/forums/thread/667597 https://developer.apple.com/forums/thread/742992 https://developer.apple.com/forums/thread/728063 but it's been a while since any of these threads were updated, and we've made attempts to address it off the suggestions in the threads to no avail. Those suggestions are: Switching to a .pkg installer from a .dmg As part of the .pkg preinstall, doing all of the following: Stopping the VPN (scutil --nc stop), shutting down the app (using osascript 'quit app id'), and deleting the app (which claims to delete the network extension, but not the approval in Login Items & Extensions remains??), by running rm -rf on the bundle in /Applications As part of the .pkg postinstall: Forcing macOS to ingest the App bundle's notarization ticket using spctl --assess. Ensuring NSXPCListener.resume() is called after autoreleasepool { NEProvider.startSystemExtensionMode() } (mentioned in a forum thread above as a fix, did not help.) One thing I'm particularly interested in is the outcome of this feedback assistant ticket, as I can't view it: FB11086599. It was shared on this forum in the first thread above, and supposedly describes the same issue. I almost find it hard to believe that this issue has been around for this many years without a workaround (there's system network extension apps out there that appear to work fine when updating, are they not using XPC?), so I wonder if there's a fix described in that FB ticket. Since I can't view that above feedback ticket, I've created my own: FB17032197
Replies
8
Boosts
0
Views
1.9k
Activity
Jun ’26
Sandboxed App <> Launch Agent - how to communicate?
I’m building a sandboxed macOS App Store app that registers an agent using SMAppService. I’m trying to understand the IPC setup between the main app and the SMAppService-managed agent. The obvious options seem to be: XPC with a Mach service But from what I understand, I’d need a special entitlement that allows me to communicate over XPC Mach service - which is unlikely to pass Mac App Store review. So how do people communicate with processes registered with SMAppService?
Replies
2
Boosts
0
Views
1.1k
Activity
Jun ’26
Can SMAppService Daemon replace SMJobBless for exclusive HID capture from keyboards?
To gain exclusive access to keyboard HID devices like Amazon Fire Bluetooth remote controls, my app has been installing a privileged helper tool with SMJobBless in the past. The app - which also has Accessibility permissions - then invoked and communicated with that helper tool through XPC. Now I'm looking into replacing that with a daemon installed through the newer SMAppService APIs, but running into a permission problem: If I try to exclusively open a keyboard HID device from the SMAppService-registered XPC service/daemon (which runs as root as seen in Activity Monitor), IOHIDDeviceOpen returns kIOReturnNotPermitted. I've spent many hours now trying to get it to work, but so far didn't find a solution. Could it be that XPC services registered as a daemon through SMAppService do not inherit the TCC permissions from the invoking process (here: Accessibility permissions) - and the exclusive IOHIDDeviceOpen therefore fails?
Replies
9
Boosts
0
Views
987
Activity
Jun ’26
XPC can't activate after app upgrade
I have an app with a system network extension. After app upgrade some customers experience broken XPC that they fix by restarting the computer. The app cannot recover by re-launching the tunnel or retrying xpc after 3 seconds. I do OSSystemExtensionRequest.activationRequest on app start and actionForReplacingExtension has .replace. I haven't experienced this before and I don't think I've changed anything, so perhaps macOS 26 has changed xpc handling. Current fix proposal is to deactivate&activate the sysext when vpn is connected, but xpc fails to connect. It's better than computer restart, but it's still not a nice user experience, because user action is required to reenable the sysext. Do you have better ideas? The system logs below show failed xpc connection after upgrade 2026-05-21 12:09:43.017192-0700 0x5b640 Default 0x0 1 0 launchd: [system:] service inactive: NetworkExtension.com.company.macos.stg.tunnelprovider.2026.124.124909 2026-05-21 12:09:43.132350-0700 0x5b7f5 Default 0x0 1 0 launchd: [system/NetworkExtension.com.company.macos.stg.tunnelprovider.2026.124.124909 [78132]:] Successfully spawned com.company.macos.stg.tunnelprovider[78132] because xpc event 2026-05-21 12:09:43.192084-0700 0x5bd02 Default 0x0 78132 0 com.company.macos.stg.tunnelprovider: (libxpc.dylib) [com.apple.xpc:connection] [0x103b01f70] activating connection: mach=true listener=true peer=false name=6GX8KVTR9H.com.company.stg.service 2026-05-21 12:09:43.195957-0700 0x5b640 Default 0x0 1 0 launchd: [system:] failed lookup: name = com.apple.pasteboard.1, requestor = com.company.ma[78132], error = 3: No such process 2026-05-21 12:09:43.246588-0700 0x5b640 Default 0x0 1 0 launchd: [system:] failed lookup: name = com.apple.securityd.xpc, requestor = com.company.ma[78132], error = 3: No such process 2026-05-21 12:09:43.994210-0700 0x5b47a Default 0x0 1 0 launchd: [gui/501 [100025]:] service inactive: application.com.company.macos.stg.155106945.155106951 2026-05-21 12:09:43.996937-0700 0x5b47a Default 0x0 1 0 launchd: [gui/501 [100025]:] removing service: application.com.company.macos.stg.155106945.155106951 2026-05-21 12:09:50.175890-0700 0x5be9d Default 0x0 78205 0 Company Stg: (libxpc.dylib) [com.apple.xpc:connection] [0xc32c92080] activating connection: mach=true listener=false peer=false name=com.company.macos.stg-spks 2026-05-21 12:09:50.175937-0700 0x5b7f5 Default 0x0 1 0 launchd: [gui/501 [100025]:] failed lookup: name = com.company.macos.stg-spks, requestor = Company Stg[78205], error = 3: No such process 2026-05-21 12:09:50.602809-0700 0x5b7f5 Default 0x0 1 0 launchd: [system/NetworkExtension.com.company.macos.stg.tunnelprovider.2026.140.125099:] The endpoint "6GX8KVTR9H.com.company.stg.service" defined in plist already exists and is owned by: NetworkExtension.com.company.macos.stg.tunnelprovider.2026.124.124909 2026-05-21 12:09:50.605301-0700 0x5b7f5 Default 0x0 1 0 launchd: [system:] service inactive: NetworkExtension.com.company.macos.stg.tunnelprovider.2026.124.124909 2026-05-21 12:09:50.605302-0700 0x5b7f5 Default 0x0 1 0 launchd: [system:] removing service: NetworkExtension.com.company.macos.stg.tunnelprovider.2026.124.124909 2026-05-21 12:09:50.662682-0700 0x5b47a Default 0x0 1 0 launchd: [system/NetworkExtension.com.company.macos.stg.tunnelprovider.2026.140.125099 [78238]:] Successfully spawned com.company.macos.stg.tunnelprovider[78238] because xpc event 2026-05-21 12:09:52.396190-0700 0x5bfd6 Default 0x0 78238 0 com.company.macos.stg.tunnelprovider: (libxpc.dylib) [com.apple.xpc:connection] [0x103839c60] activating connection: mach=true listener=true peer=false name=6GX8KVTR9H.com.company.stg.service 2026-05-21 12:09:52.396217-0700 0x5bfcf Default 0x0 1 0 launchd: [system:] failed activation: name = 6GX8KVTR9H.com.company.stg.service, flags = 0x0, requestor = com.company.ma[78238], error = 1: Operation not permitted 2026-05-21 12:09:52.399064-0700 0x5b47a Default 0x0 1 0 launchd: [system:] failed lookup: name = com.apple.pasteboard.1, requestor = com.company.ma[78238], error = 3: No such process 2026-05-21 12:09:52.450706-0700 0x5bfcf Default 0x0 1 0 launchd: [system:] failed lookup: name = com.apple.securityd.xpc, requestor = com.company.ma[78238], error = 3: No such process 2026-05-21 12:09:52.607836-0700 0x5be9d Default 0x0 78205 0 Company Stg: (libxpc.dylib) [com.apple.xpc:connection] [0xc3295d7c0] activating connection: mach=true listener=false peer=false name=6GX8KVTR9H.com.company.stg.service 2026-05-21 12:09:52.607964-0700 0x5b47a Default 0x0 1 0 launchd: [system:] failed lookup: name = 6GX8KVTR9H.com.company.stg.service, flags = 0x8, requestor = Company Stg[78205], error = 3: No such process 2026-05-21 12:09:55.610528-0700 0x5be9d Default 0x0 78205 0 Company Stg: (libxpc.dylib) [com.apple.xpc:connection] [0xc3295de00] activating connection: mach=true listener=false peer=false name=6GX8KVTR9H.com.company.stg.service 2026-05-21 12:09:55.610694-0700 0x5b47a Default 0x0 1 0 launchd: [system:] failed lookup: name = 6GX8KVTR9H.com.company.stg.service, flags = 0x8, requestor = Company Stg[78205], error = 3: No such process
Replies
2
Boosts
0
Views
751
Activity
May ’26
XPC Communication between Editor app and user-compiled code
Hello! I'm trying to implement an editor app (macOS) that allows the user to write code, which will be compiled and executed, showing the result in the editor window. Imagine it like SwiftUI previews, but the graphic output is created with Metal, not SwiftUI. I found that IOSurface can be used to share that kind of data over XPC, so I would not have to rely on the private NSRemoteView. However, I'm confused if it is, at all, possible for my editor app to connect to an XPC Service, that was NOT bundled with it (but compiled by it at runtime). I succeeded to launch an XPC service defined as: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.myteam.myproject.service</string> <key>MachServices</key> <dict> <key>com.myteam.myproject.service</key> <true/> </dict> <key>Program</key> <string>/Path/to/service/run_my_service.sh</string> </dict> </plist> But the call to let connection = NSXPCConnection(machServiceName: "com.myteam.myproject.service") let proxy = connection.remoteObjectProxyWithErrorHandler { error in continuation.resume(throwing: error) } as? MyServiceProtocol fails with "The connection to service named com.myteam.myproject.service was invalidated: Connection init failed at lookup with error 3 - No such process." I have added <key>com.apple.security.temporary-exception.mach-lookup.global-name</key> <array> <string>com.myteam.myproject.service</string> </array> to my entitlements. Since the tutorials I followed are quite old, I'm wondering if support for something like this was dropped at some point. Thanks for any advice!
Replies
6
Boosts
0
Views
1.7k
Activity
May ’26
How much practical benefit is there to XPC-based privilege separation?
"Privilege separation" is one of the "two main reasons to use XPC services" given by https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingXPCServices.html — With traditional applications, if an application becomes compromised through a buffer overflow or other security vulnerability, the attacker gains the ability to do anything that the user can do. To mitigate this risk, Mac OS X provides sandboxing—limiting what types of operations a process can perform. […] Each XPC service has its own sandbox, so XPC services can make it easier to implement proper privilege separation. The idea (iiuc) being that if the main process is compromised, the spicier operations have been separated out to a separate process space, and this improves the security of the system. But if the main process is compromised, and that main process is trusted by the more-privileged XPC service, is not the system still compromised in practice? That is rather than the exploit being: exploit some vulnerability gain arbitrary code execution do something naughty isn't the same still possible with just one extra step: exploit vulnerability arbitrary execution ask the XPC service nicely… …to do something naughty?
Replies
3
Boosts
0
Views
454
Activity
May ’26
XPC connection broken on app & extension upgrade
Post app update our extension version is replaced with the new version. However occasionally maybe around 20% of the time The XPC connection we have for communication between the app and extension will not work. We have reconnection retry logic as well as tried stop and starting the extension but it appears once its broken its broken and all that fixes it is a machine restart. This is obviously not ideal. I have noticed a few other forums talking about the same or similar problem. https://developer.apple.com/forums/thread/728063 https://developer.apple.com/forums/thread/779395 https://developer.apple.com/forums/thread/742992 When we run on a broken upgrade cycle `sudo launchctl print system/NetworkExtension.com.company.example.app.filter.5.5.0.2248 ` We notice that endpoints is missing from the log. However if we run the same command in terminal for a working upgrade cycle endpoints = {} exist. Therefore for some reason our xpc isn't actually getting registered.
Replies
1
Boosts
0
Views
892
Activity
May ’26
XPC connection broken on app & extension upgrade
After an app update replaces our extension with the new version, the XPC connection between the app and the extension fails to work roughly 20% of the time. Once it's broken, it stays broken — our reconnect/retry logic doesn't recover it, stopping and starting the extension doesn't recover it, and the only thing that fixes it is a full machine restart. This obviously isn't ideal. I've seen a few other threads describing the same or a very similar issue: https://developer.apple.com/forums/thread/728063 https://developer.apple.com/forums/thread/779395 https://developer.apple.com/forums/thread/742992 On a broken upgrade cycle, when we run: sudo launchctl print system/NetworkExtension.com.company.example.app.filter.5.5.0.2248 the endpoints entry is missing from the output entirely. On a working upgrade cycle, the same command shows endpoints = {} is present. So it looks like our XPC service isn't actually getting registered with launchd in the broken case. We've tried various changes to our connection logic, but nothing prevents the issue — random upgrades still end up broken with no obvious cause. Is there a known way to recover the XPC registration without requiring a machine restart?
Replies
1
Boosts
0
Views
879
Activity
May ’26
XPC doesn't work with network extension on app upgrade
Our app has a network extension (as I've mentioned lots 😄). We do an upgrade by downloading the new package, stopping & removing all of our components except for the network extension, and then installing the new package, which then loads a LaunchAgent causing the containing app to run. (The only difference between a new install and upgrade is the old extension is left running, but not having anything to tell it what to do, just logs and continues.) On some (but not all) upgrades... nothing ends up able to communicate via XPC with the Network Extension. My simplest cli program to talk to it gets Could not create proxy: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named blah was invalidated: failed at lookup with error 3 - No such process." UserInfo={NSDebugDescription=The connection to service named bla was invalidated: failed at lookup with error 3 - No such process.} Could not communicate with blah Restarting the extension by doing a kill -9 doesn't fix it; neither does restarting the control daemon. The only solution we've come across so far is rebooting. I filed FB11086599 about this, but has anyone thoughts about this?
Replies
20
Boosts
2
Views
5.3k
Activity
May ’26
How to debug a Launch Daemon that requires an App Group provisioning profile for XPC communication
Hello, I am developing a macOS Launch Daemon (packaged as a bundle) that acts as an XPC server. For debugging purposes, I am trying to run the daemon's executable directly from the terminal via sudo ./mydaemon.app/Contents/MacOS/myexecutable. Initially, I added the com.apple.security.application-groups entitlement to the daemon. However, when starting the process, it failed to create the XPC service with the following errors: Unsatisfied entitlements: com.apple.security.application-groups Soft-restriction provisioning profile validation failure: Error Domain=AppleMobileFileIntegrityError Code=-413 "No matching profile found" UserInfo={NSURL=, unsatisfiedEntitlements=, NSLocalizedDescription=No matching profile found} listener failed to activate: xpc_error=[1: Operation not permitted] To resolve the profile validation failure, I registered a new App Group in the Apple Developer Portal, generated a new provisioning profile for the daemon that includes this group, and embedded it into the bundle (Contents/embedded.provisionprofile). Now, the previous profile error is gone, but I am getting a new identity conflict error, and the XPC listener still fails: Two equal instances have unequal identities. <anon<myproc_name>(501) pid=2818 AUID=501> and <anon<myproc_name>(501)(262) pid=2818 AUID=262> listener failed to activate: xpc_error=[1: Operation not permitted] My questions are: What exactly causes the Two equal instances have unequal identities error? I noticed the Audit UID difference (AUID=501 vs AUID=262). Why does NSXPCListener still fail with Operation not permitted? What is the recommended workflow for debugging a Launch Daemon that requires an App Group provisioning profile for XPC communication? Thank you in advance!
Replies
2
Boosts
0
Views
1.2k
Activity
Apr ’26