DNS Proxy system extension – OSSystemExtensionErrorDomain error 9 “validationFailed” on clean macOS machine

Hi,

I’m implementing a macOS DNS Proxy as a system extension and running into a persistent activation error:

OSSystemExtensionErrorDomain error 9 (validationFailed) with the message: extension category returned error

This happens both on an MDM‑managed Mac and on a completely clean Mac (no MDM, fresh install).

Setup macOS: 15.x (clean machine, no MDM)

Xcode: 16.x

Team ID: AAAAAAA111 (test)

Host app bundle ID: com.example.agent.NetShieldProxy

DNS Proxy system extension bundle ID: com.example.agent.NetShieldProxy.dnsProxy

The DNS Proxy is implemented as a NetworkExtension system extension, not an app extension.

Host app entitlements From codesign -d --entitlements :- /Applications/NetShieldProxy.app:

xml <dict> <key>com.apple.application-identifier</key> <string>AAAAAAA111.com.example.agent.NetShieldProxy</string>

<key>com.apple.developer.system-extension.install</key>
<true/>

<key>com.apple.developer.team-identifier</key>
<string>AAAAAAA111</string>

<key>com.apple.security.app-sandbox</key>
<true/>

<key>com.apple.security.application-groups</key>
<array>
    <string>group.com.example.NetShieldmac</string>
</array>

<key>com.apple.security.files.user-selected.read-only</key>
<true/>

</dict> DNS Proxy system extension entitlements From codesign -d --entitlements :- "/Applications/NetShieldProxy.app/Contents/Library/SystemExtensions/com.example.agent.NetShieldProxy.dnsProxy.systemextension/Contents/MacOS/com.example.agent.NetShieldProxy.dnsProxy":

xml <dict> <key>com.apple.application-identifier</key> <string>AAAAAAA111.com.example.agent.NetShieldProxy.dnsProxy</string>

<key>com.apple.developer.networking.networkextension</key>
<array>
    <string>dns-proxy-systemextension</string>
</array>

<key>com.apple.developer.team-identifier</key>
<string>AAAAAAA111</string>

<key>com.apple.security.application-groups</key>
<array>
    <string>group.com.example.NetShieldmac</string>
    <string>group.example.NetShieldmac</string>
    <string>group.example.agent.enterprise.macos</string>
    <string>group.example.com.NetShieldmac</string>
</array>

</dict> Both host and extension binaries are signed with the same Developer ID Application certificate for Team AAAAAAA111, and codesign -dv --verbose=4 shows matching TeamIdentifier and Authority for both. ​

DNS Proxy system extension Info.plist On the clean Mac, from:

bash plutil -p "/Applications/NetShieldProxy.app/Contents/Library/SystemExtensions/com.example.agent.NetShieldProxy.dnsProxy.systemextension/Contents/Info.plist" I get:

json { "CFBundleExecutable" => "com.example.agent.NetShieldProxy.dnsProxy", "CFBundleIdentifier" => "com.example.agent.NetShieldProxy.dnsProxy", "CFBundleName" => "com.example.agent.NetShieldProxy.dnsProxy", "CFBundlePackageType" => "SYSX", "CFBundleShortVersionString" => "1.0.1.8", "CFBundleSupportedPlatforms" => [ "MacOSX" ], "CFBundleVersion" => "0.1.1", "LSMinimumSystemVersion" => "13.5", "NSExtension" => { "NSExtensionPointIdentifier" => "com.apple.dns-proxy", "NSExtensionPrincipalClass" => "com_example_agent_NetShieldProxy_dnsProxy.DNSProxyProvider" }, "NSSystemExtensionUsageDescription" => "SYSTEM_EXTENSION_USAGE_DESCRIPTION" } The DNSProxyProvider class inherits from NEDNSProxyProvider and is built in the system extension target.

Activation code In the host app, I use:

swift import SystemExtensions

final class SystemExtensionActivator: NSObject, OSSystemExtensionRequestDelegate { private let extensionIdentifier = "com.example.agent.NetShieldProxy.dnsProxy"

func activate(completion: @escaping (Bool) -> Void) {
    let request = OSSystemExtensionRequest.activationRequest(
        forExtensionWithIdentifier: extensionIdentifier,
        queue: .main
    )
    request.delegate = self
    OSSystemExtensionManager.shared.submitRequest(request)
}

func request(_ request: OSSystemExtensionRequest,
             didFailWithError error: Error) {
    let nsError = error as NSError
    print("Activation failed:", nsError)
}

func request(_ request: OSSystemExtensionRequest,
             didFinishWithResult result: OSSystemExtensionRequest.Result) {
    print("Result:", result.rawValue)
}

} Runtime behavior on a clean Mac (no MDM) config.plist is created under /Library/Application Support/NetShield (via a root shell script).

A daemon runs, contacts our backend, and writes /Library/Application Support/NetShield/state.plist with a valid dnsToken and other fields.

The app NetShieldProxy.app is installed via a notarized, stapled Developer ID .pkg.

The extension bundle is present at: /Applications/NetShieldProxy.app/Contents/Library/SystemExtensions/com.example.agent.NetShieldProxy.dnsProxy.systemextension.

When I press Activate DNS Proxy in the UI, I see in the unified log:

text NetShieldProxy: [com.example.agent:SystemExtensionActivator] Requesting activation for system extension: com.example.agent.NetShieldProxy.dnsProxy NetShieldProxy: [com.example.agent:SystemExtensionActivator] SystemExtensionActivator - activation failed: extension category returned error (domain=OSSystemExtensionErrorDomain code=9) NetShieldProxy: [com.example.agent:SystemExtensionActivator] SystemExtensionActivator - OSSystemExtensionError code enum: 9 NetShieldProxy: [com.example.agent:SystemExtensionActivator] SystemExtensionActivator - validationFailed And:

bash systemextensionsctl list

-> 0 extension(s)

There is no prompt in Privacy & Security on this clean Mac.

Question Given:

The extension is packaged as a system extension (CFBundlePackageType = SYSX) with NSExtensionPointIdentifier = "com.apple.dns-proxy".

Host and extension share the same Team ID and Developer ID Application cert.

Entitlements on the target machine match the provisioning profile and Apple’s docs for DNS Proxy system extensions (dns-proxy-systemextension).

This is happening on a clean Mac with no MDM profiles at all.

What are the likely reasons for OSSystemExtensionErrorDomain error 9 (validationFailed) with "extension category returned error" in this DNS Proxy system extension scenario?

Is there any additional configuration required for DNS Proxy system extensions (beyond entitlements and Info.plist) that could trigger this category-level validation failure?

Any guidance or examples of a working DNS Proxy system extension configuration (host entitlements + extension Info.plist + entitlements) would be greatly appreciated.

Thanks!

Answered by DTS Engineer in 872704022

You post is quite hard to read. I recommend that you review the advice in Quinn’s Top Ten DevForums Tips, and specifically the stuff about code blocks in tip 5.

What are the likely reasons for … extension category returned error

I discuss the concept of the extension category in this post. The rest of that thread should have some useful hints and tips.


Taking a step back, you’re clearly testing the direct distribution case here, that is, where the sysex uses Developer ID signing. I’d like to clarify the context for that:

  • Do you already have this working with Apple Development signing? That is, this code is working at your desk but fails when you deploy it using Developer ID signing?
  • Or is this the first time you’ve tested your code?

If it’s the latter, I recommend that you stop using Developer ID and instead switch to Apple Development. That’s a good idea in general — see The Care and Feeding of Developer ID for more on that — but in the case of an NE sysex it actively makes your day-to-day development easier. I explain this process in some detail in Debugging a Network Extension Provider.

Share and Enjoy

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

You post is quite hard to read. I recommend that you review the advice in Quinn’s Top Ten DevForums Tips, and specifically the stuff about code blocks in tip 5.

What are the likely reasons for … extension category returned error

I discuss the concept of the extension category in this post. The rest of that thread should have some useful hints and tips.


Taking a step back, you’re clearly testing the direct distribution case here, that is, where the sysex uses Developer ID signing. I’d like to clarify the context for that:

  • Do you already have this working with Apple Development signing? That is, this code is working at your desk but fails when you deploy it using Developer ID signing?
  • Or is this the first time you’ve tested your code?

If it’s the latter, I recommend that you stop using Developer ID and instead switch to Apple Development. That’s a good idea in general — see The Care and Feeding of Developer ID for more on that — but in the case of an NE sysex it actively makes your day-to-day development easier. I explain this process in some detail in Debugging a Network Extension Provider.

Share and Enjoy

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

Thanks for the pointers and links.

To answer your question: this is actually the first time I’m bringing up this NE system extension. I started directly with Developer ID because the final goal is MDM deployment, but I haven’t yet verified the setup with Apple Development signing.

I’ll now switch both the host app and the DNS Proxy system extension to Apple Development signing, follow the “System Extension Hints” and “Debugging a Network Extension Provider” flow (post‑build copy to /Applications, run from there, first‑light log in main.swift, attach debugger, etc.), and see if the provider can be started successfully in that configuration.

If I still get OSSystemExtensionErrorDomain error 9 / “extension category returned error” with Apple Development signing on a clean dev machine, I’ll update this thread with the exact steps, logs, and configuration.

I updated the App ID for the DNS Proxy system extension and noticed that Developer Portal only exposes the legacy dns-proxy value under Network Extensions. There is no option for dns-proxy-systemextension.

My extension’s entitlements currently contain:

xml <key>com.apple.developer.networking.networkextension</key>
<array>
<string>dns-proxy-systemextension</string>
</array>
When I create a Mac App Development provisioning profile for this App ID and try to use it for signing the system extension target, Xcode fails with:

Provisioning profile "Dev-Mac-App-DNSProxy" doesn't match the entitlements file's value for the com.apple.developer.networking.networkextension entitlement.

So at this point the entitlements and the Developer Portal capabilities cannot be made to match: the profile only knows about dns-proxy, while my extension needs dns-proxy-systemextension.

Is dns-proxy-systemextension the correct entitlement value for a DNS Proxy packaged as a system extension today, and if so, how should this be represented/configured in the Developer Portal so that the Mac App Development profile matches the entitlement?

this is actually the first time I’m bringing up this NE system extension.

In that case I recommend that you switch to using Apple Development signing.

Using Developer ID for day-to-day development is a bad idea in general, as I explained in that other post, but it causes significant grief in the case of NE system extensions:

  • If you’re using Xcode, you run into the entitlement suffix issue you’ve noticed. For more on that, see Exporting a Developer ID Network Extension.
  • The system requires that Developer ID-signed system extensions be notarised, so you have to notarise your app before each test O-:

ps It’s better to reply as a reply, rather than in the comments; see Quinn’s Top Ten DevForums Tips for this and other titbits.

Share and Enjoy

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

Thanks for the clarification about Developer ID vs Apple Development and for the links.

Previously I started with Developer ID and the dns-proxy-systemextension entitlement, but per your advice I’ve now switched both the host app and the DNS Proxy system extension to Apple Development signing and the legacy dns-proxy value.

Current Apple Development setup

macOS: 15.7.3 (24G419)

Xcode: 26.2 (17C52)

Host: com.example.agent.MyMacProxy

DNS Proxy system extension: com.example.agent.MyMacProxy.dnsProxy

System extension entitlement:

xml <key>com.apple.developer.networking.networkextension</key> <array> <string>dns-proxy</string> </array> System extension Info.plist (built .systemextension inside the host app):

xml <key>NSExtension</key> <dict> <key>NSExtensionPointIdentifier</key> <string>com.apple.system_extension.network_extension</string> <key>NSExtensionPrincipalClass</key> <string>MyMacProxy.DNSProxyProvider</string> </dict> There is no NetworkExtension key in this plist (confirmed with plutil -p on the built .systemextension in both DerivedData and /Applications).

The system extension is embedded at:

MyMacProxy.app/Contents/Library/SystemExtensions/com.example.agent.MyMacProxy.dnsProxy.systemextension

The host app (from /Applications) configures DNS Proxy via NEDNSProxyManager with:

swift providerBundleIdentifier = "com.example.agent.MyMacProxy.dnsProxy" What happens

If I add a NetworkExtension dictionary with NEProviderClasses and try different keys like:

dns-proxy

DNSProxy

NEDNSProxy

I consistently get Code=4 errors such as:

text Validating system extension com.example.agent.MyMacProxy.dnsProxy System Extension validation failed: Error Domain=NetworkExtensionErrorDomain Code=4 "The system extension com.example.agent.MyMacProxy.dnsProxy has an invalid extension point in its NetworkExtension key in its Info.plist: dns-proxy." If I then remove the NetworkExtension dictionary entirely (leaving only the NSExtension dict shown above), Code=4 goes away, but nesessionmanager still reports Code=2 about NetworkExtension needing to be a non‑empty dictionary, even though that key is no longer present in the current Info.plist.

I’ve tried:

removing the standalone .systemextension product (keeping only the embedded one)

systemextensionsctl uninstall <team> com.example.agent.MyMacProxy.dnsProxy and systemextensionsctl reset

killing nesessionmanager / systemextensionsd

rebooting and reinstalling the host app into /Applications

The behaviour doesn’t change.

Questions

For a DNS Proxy implemented as a Network Extension system extension under Apple Development signing, is the intended pattern to have no NetworkExtension dictionary at all (only NSExtensionPointIdentifier = com.apple.system_extension.network_extension plus the dns-proxy entitlement), or should DNS Proxy system extensions still declare a NetworkExtension dictionary with NEProviderClasses?

If a NetworkExtension dictionary is required, what are the currently valid keys for a DNS Proxy system extension (given that dns-proxy, DNSProxy, and NEDNSProxy all trigger Code=4 for “invalid extension point”)?

If you have a minimal, known‑good DNS Proxy system extension sample (Info.plist + entitlements) that passes this validation on current macOS, that would be extremely helpful as a reference.

DNS Proxy system extension – OSSystemExtensionErrorDomain error 9 “validationFailed” on clean macOS machine
 
 
Q