NETunnelProviderManager.saveToPreferences() fails with permission denied on macOS

I'm developing a macOS app using a Network Extension Packet Tunnel Provider. The System Extension activates successfully, but NETunnelProviderManager.saveToPreferences() consistently fails with permission denied.

Environment

  • macOS virtual machine running under UTM
  • Host app and embedded Packet Tunnel System Extension signed with Developer ID
  • App notarization verified successfully
  • System Extension status: [activated enabled]
  • Packet Tunnel has com.apple.security.app-sandbox=true and com.apple.security.network.client=true
  • Host app has the Network Extension entitlement

Reproduction

  1. Launch the installed, notarized HostApp.
  2. Call NETunnelProviderManager.loadAllFromPreferences().
  3. No manager matching the Packet Tunnel provider bundle identifier is found.
  4. Create a NETunnelProviderManager.
  5. Configure NETunnelProviderProtocol with the Packet Tunnel provider bundle identifier and a server address.
  6. Set localizedDescription and isEnabled = true.
  7. Call saveToPreferences().

Observed result

On October 30, 2026, the following events were recorded:

11:25:32.643 PROTOTYPE_MANAGER_CREATED
11:25:32.643 PREFERENCES_LOADED
11:25:32.643 PROTOTYPE_VPN_AUTH_SKIPPED
11:25:32.646 Saving configuration ... with existing signature (null)
11:25:33.766 NEConfigurationErrorDomain Code=10 "permission denied"
11:25:33.766 NEVPNErrorDomain Code=5 "permission denied"

The app never reaches startVPNTunnel().

What I've already checked

  • Developer ID code signing verification succeeds.
  • Notarization and stapler validation succeed.
  • The System Extension is activated and enabled.
  • The failure reproduces both with and without created.loadFromPreferences() before saving.
  • An explicit VPN authorization step is disabled in these reproduction runs.

Questions

  1. What conditions can cause NEConfigurationErrorDomain Code=10 when a newly created NETunnelProviderManager is saved?
  2. Are there additional signing, entitlement, authorization, or configuration requirements for a Developer ID-distributed macOS Packet Tunnel app?
  3. Which NetworkExtension or nehelper diagnostics would help identify the specific permission check that fails?
  4. Is there any known difference in this behavior when running under macOS virtualization?

I can provide a minimal reproduction project, sanitized logs, entitlement output, and a sysdiagnose privately if necessary.

Thank you for your guidance.

Answered by DTS Engineer in 913961022

Testing this stuff in a VM should be fine. I do that regularly.

I advise against using Developer ID code signing for day-to-day work. See The Care and Feeding of Developer ID for a whole world of background as to that recommendation.

Also, Developer ID has some special constraints when it comes to Network Extension. See Exporting a Developer ID Network Extension.

So, are you using Developer ID to do your distribution testing? Meaning that everything works when you sign with Apple Development but then fail when you switch to Developer ID.

Or are using Developer ID for day-to-day development? Because in that case my advice is:

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

Testing this stuff in a VM should be fine. I do that regularly.

I advise against using Developer ID code signing for day-to-day work. See The Care and Feeding of Developer ID for a whole world of background as to that recommendation.

Also, Developer ID has some special constraints when it comes to Network Extension. See Exporting a Developer ID Network Extension.

So, are you using Developer ID to do your distribution testing? Meaning that everything works when you sign with Apple Development but then fail when you switch to Developer ID.

Or are using Developer ID for day-to-day development? Because in that case my advice is:

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