`sysextd` rejects new `NEFilterDataProvider` activation with "no policy" on macOS 26 — despite valid Developer ID + notarization

I'm building a macOS network monitor using NEFilterDataProvider as a system extension, distributed with Developer ID signing. On macOS 26.3 (Tahoe), sysextd consistently rejects the activation request with "no policy, cannot allow apps outside /Applications" — despite the app being in /Applications and passing every verification check.

I'm aware of the known Xcode NE signing bug (r. 108838909) and have followed the manual signing process from Exporting a Developer ID Network Extension. I've also tried both xcodebuild build and xcodebuild archive workflows — identical failure.


Environment

macOS26.3 (25D125), SIP enabled
Xcode26.3 (17C529)
HardwareApple M2 Pro
CertificateDeveloper ID Application (issued Jan 30, 2026 — 27 days old)
MDM/ProfilesNone installed

Signing & Verification (all pass)

$ spctl -a -vv /Applications/Chakshu.app
/Applications/Chakshu.app: accepted
source=Notarized Developer ID
origin=Developer ID Application: ROBIN SHARMA (R65679C4F3)

$ codesign --verify --deep --strict -vv /Applications/Chakshu.app
/Applications/Chakshu.app: valid on disk
/Applications/Chakshu.app: satisfies its Designated Requirement

$ xcrun stapler validate /Applications/Chakshu.app
The validate action worked!

App signing:

Authority=Developer ID Application: ROBIN SHARMA (R65679C4F3)
Authority=Developer ID Certification Authority
Authority=Apple Root CA
TeamIdentifier=R65679C4F3
Runtime Version=26.2.0
Notarization Ticket=stapled

App entitlements:

com.apple.application-identifier = R65679C4F3.dev.indrasvat.chakshu
com.apple.developer.team-identifier = R65679C4F3
com.apple.developer.system-extension.install = true
com.apple.developer.networking.networkextension = [content-filter-provider-systemextension]
keychain-access-groups = [R65679C4F3.*]

Extension signing: Same Developer ID authority, same team, same timestamp. Extension entitlements match (minus system-extension.install). Developer ID provisioning profiles are embedded in both app and extension.


What sysextd logs

Captured Feb 26, 2026 from log stream --predicate 'process == "sysextd"':

sysextd  [com.apple.sx:XPC] client activation request for dev.indrasvat.chakshu.filter
sysextd  attempting to realize extension with identifier dev.indrasvat.chakshu.filter
sysextd  (Security) SecKeyVerifySignature     ← pass (×2)
sysextd  (Security) SecTrustEvaluateIfNecessary  ← pass (×2)
sysextd  [com.apple.xpc:connection] activating connection: name=com.apple.CodeSigningHelper
sysextd  [com.apple.xpc:connection] invalidated after the last release
sysextd  no policy, cannot allow apps outside /Applications
sysextd  [com.apple.sx:XPC] client connection invalidated

Signature and trust evaluation pass. CodeSigningHelper completes. Then the policy check fails. The app receives OSSystemExtensionError code 4 (extensionNotFound).


What I've tried and ruled out

Build process:

ApproachResult
xcodebuild build -configuration Release + manual re-signSame failure
xcodebuild archive + export from archive + manual re-sign (per thread/737894)Same failure
Minimal hand-crafted Xcode project (no xcodegen, trivial code)Same failure

Both workflows follow Quinn's process exactly: build with Apple Development → copy app → embed Developer ID provisioning profiles → re-sign inside-out (extension first, then app) with -systemextension suffix entitlements → notarize → staple → install to /Applications.

System-level checks:

  • Rebooting — no change
  • Killing sysextd — no change
  • Removing com.apple.quarantine xattr — no change
  • chown root:wheel on app bundle — no change
  • lsregister -r (reset Launch Services) — no change
  • Waiting 27 days for certificate propagation — no change
  • Reinstalling via Finder drag-to-Applications — no change
  • No MDM or configuration profiles installed
  • /Library/SystemExtensions/db.plist shows extensionPolicies: [] (empty)

Key observation

Pre-existing network extensions activated before macOS 26 work fine on this machine. For example, Tailscale's NEPacketTunnelProvider shows state: activated_enabled in the system extensions database — it was activated on a prior macOS version and is still running. Only new system extension activations fail.

I've seen similar Tahoe-specific reports from LuLu (same NEFilterDataProvider type, Developer ID distribution):


Questions

  1. Is this a known regression in macOS 26's sysextd policy evaluation for new Developer ID system extension activations?
  2. sysextd's policy check fails after all signature and trust evaluation succeeds. Is there a separate trust/policy path that sysextd consults beyond what spctl, codesign, and CodeSigningHelper verify?
  3. Is there anything else I should be checking?

I have a sysdiagnose captured immediately after the failure, a minimal reproducer project, and full raw sysextd logs available on request.

Answered by DTS Engineer in 877639022

The no policy, cannot allow apps outside /Applications log entry is a red herring. It’s being emitted by the code that determines the current activation policy. The log entry indicates that there is no policy, and thus the default policy applies, which means that the container app must be in the Applications folder.

Notably, the code that logs this is a function that isn’t passed any information about your app, and thus it’s literally impossible for it to change behaviour based on whether your app is or isn’t in the Applications folder. This is normal.

The next log entry, client connection invalidated, is more of a concern. It suggests that sysextd was using XPC to talk to some helper service and that helper service went away. I’ve seen issues like that before, where the structure of your sysex causes a helper service to crash (well, trap).

See this thread, starting at this post, but also see this thread. And also check for any NE-related crash reports.

Share and Enjoy

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

Had Claude analyze the sysdiagnose report. Here are the findings:

Main observation: sysdiagnose analysis reveals sysextd never consults syspolicyd during activation

$ sudo sysdiagnose -f ~/Desktop/
This tool generates files that allow Apple to investigate issues with your
computer and help improve Apple products. The files might contain personal
information found on your device or associated with your Apple Account(s),
including but not limited to your name, serial numbers of your device,
your device name, your attached peripheral devices, your user name, your
email address and email settings, file paths, file names, Siri suggestions,
your computer's IP addresses, network connection information, and profiles
installed to your device.

This information is used by Apple in accordance with its privacy policy
(www.apple.com/privacy) and is not shared with any other company. By using
this tool and sending the results to Apple, you consent to Apple using the
contents of these files to improve Apple products.

Press 'Enter' to continue. Ctrl+\ to cancel.

Progress:
[|||||||||||||||||||||||||||||||||||||||100%|||||||||||||||||||||||||||||||||||]

Output available at '~/Desktop/sysdiagnose_2026.02.26_12-50-09-0800_macOS_Mac_25D125.tar.gz'.

The complete timeline (Feb 26, 12:49 PST):

TimeProcessEvent
12:49:00.624syspolicydGK performScan — team: R65679C4F3
12:49:00.821syspolicydGK evaluateScanResult: 3 — id: dev.indrasvat.chakshu (scan passed)
12:49:01.184syspolicydXProtect: "Forwarding detection succeeded!"
12:49:14.583ChakshuConnects to com.apple.sysextd via XPC
12:49:14.587–592sysextdVerifies host app signing — SecKeyVerifySignature × 2, SecTrustEvaluateIfNecessary × 2 (pass)
12:49:14.594sysextdCodeSigningHelperHost app check
12:49:14.598sysextd"attempting to realize extension with identifier dev.indrasvat.chakshu.filter"
12:49:14.598–601sysextdVerifies extension signing — same checks (pass)
12:49:14.601sysextdCodeSigningHelperExtension check
12:49:14.602sysextd"no policy, cannot allow apps outside /Applications"
12:49:14.605ChakshuReceives OSSystemExtensionError code 4

Three things stand out:

  1. syspolicyd is never consulted during extension activation. There are zero syspolicyd log entries between 12:49:14 and 12:49:15. The syspolicyd scan at 12:49:00 was the Gatekeeper first-run assessment on app launch — not the extension activation. Gatekeeper gave us result 3 (same as Zoom on this machine), so it's happy with us.

  2. No user approval dialog is triggered. Zero entries from UserNotificationCenter, System Settings, or any UI prompting process. On a non-MDM machine with empty extensionPolicies, sysextd should present the "allow in System Settings" dialog. Instead it goes straight to rejection.

  3. All signature verification passes. Both sysextd and trustd complete SecKeyVerifySignature and SecTrustEvaluateIfNecessary without error for both the host app and the extension. CodeSigningHelper is consulted twice and completes normally.

The failure appears to be in sysextd's internal policy lookup: it checks for an MDM/configuration profile policy (none found — extensionPolicies is empty), then fails to fall through to the user approval flow. The 1ms gap between CodeSigningHelper completing (12:49:14.601) and the "no policy" decision (12:49:14.602) suggests a simple boolean check, not a failed network call or timeout.

For comparison, Tailscale's NE on this machine (activated pre-Tahoe) only shows list/cdhash queries — never an activation flow — confirming it's grandfathered in the sysext DB as activated_enabled.

The no policy, cannot allow apps outside /Applications log entry is a red herring. It’s being emitted by the code that determines the current activation policy. The log entry indicates that there is no policy, and thus the default policy applies, which means that the container app must be in the Applications folder.

Notably, the code that logs this is a function that isn’t passed any information about your app, and thus it’s literally impossible for it to change behaviour based on whether your app is or isn’t in the Applications folder. This is normal.

The next log entry, client connection invalidated, is more of a concern. It suggests that sysextd was using XPC to talk to some helper service and that helper service went away. I’ve seen issues like that before, where the structure of your sysex causes a helper service to crash (well, trap).

See this thread, starting at this post, but also see this thread. And also check for any NE-related crash reports.

Share and Enjoy

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

Thanks for responding, Quinn! Further analysis by Claude based on your inputs.


I ran sudo sysdiagnose immediately after the failure and analyzed the system_logs.logarchive. The findings suggest our situation may be different from the threads you linked.

No crash reports and no nesessionmanager involvement:

  • Zero crash reports for sysextd, nesessionmanager, or CodeSigningHelper (checked both /Library/Logs/DiagnosticReports/ and the sysdiagnose archive)
  • Zero connection to com.apple.nesessionmanager.system-extensions interrupted messages
  • nesessionmanager has zero log entries during the activation attempt window (12:49:14–12:49:15)

The activation never reaches "staging" or "validating by category":

In thread 776759, the successful flow progresses:

activation request → realize extension → advancing state from realizing to staging → import to staging → category validation by nesessionmanager

Our flow stops before staging:

12:49:14.598  client activation request for dev.indrasvat.chakshu.filter

12:49:14.598  attempting to realize extension with identifier dev.indrasvat.chakshu.filter

              [SecKeyVerifySignature × 2, SecTrustEvaluateIfNecessary × 2 — all pass]

12:49:14.601  com.apple.CodeSigningHelper — connected and completed normally

12:49:14.602  no policy, cannot allow apps outside /Applications

12:49:14.604  client connection (pid 61491) invalidated

There are no "advancing state from realizing to staging", "Importing content", or "Container path" messages. The rejection happens in the realize phase, 1ms after CodeSigningHelper returns.

About the "client connection invalidated":

From the sysdiagnose, the "client connection invalidated" at 12:49:14.604 is sysextd tearing down the XPC connection back to our host app (pid 61491 = Chakshu) after the rejection — not a helper service crashing. The CodeSigningHelper connections at 12:49:14.594 and 12:49:14.601 both show normal completion (invalidated after the last release of the connection object), not crashes.

What nesessionmanager DOES show (but much later):

nesessionmanager has a Chakshu filter session from NEFilterManager.saveToPreferences():

NESMFilterSession[Chakshu Network Filter:30B6820D-...]: plugin NEFilterPlugin(dev.indrasvat.chakshu[content-filter][inactive])

But this is the NE configuration, not the sysex activation. At 12:50:27 (over a minute after rejection), this session is disposed with "Plugin was disabled" — which makes sense as cleanup after the failed activation.

Summary:

It appears that sysextd is rejecting during the realize phase itself, before it ever reaches category validation or contacts nesessionmanager. The "no policy" default policy check passes (our app is in /Applications), but the flow doesn't continue to staging. Something between CodeSigningHelper returning and the staging step is failing silently.

The sysdiagnose archive (sysdiagnose_2026.02.26_12-50-09-0800) is available — happy to attach it or share any specific sections.

Follow-up: Notarization ticket database analysis

I ran diagnostic queries against the three SystemPolicyConfiguration databases (ExecPolicy, SystemPolicy, Tickets) comparing my extension against a working Tailscale NE on the same machine. Here's what I found.

Tickets database

The Tickets database has two tables: tickets (direct entries) and hashes (component CDHashes linked to a parent ticket).

After xcrun stapler staple Chakshu.app:

CDHashticketshashes
Host app 02d771fe...Yes (id=940)Yes → ticket 940
Extension 658144fa...NoYes → ticket 940

For comparison, Tailscale's extension CDHash has a direct entry in tickets (id=639).

ExecPolicy policy_scan_cache

Binarypolicy_matchflags
Tailscale extension48704
My host app48704
My extension964

policy_match=4 appears to be the "Notarized Developer ID" assessment. policy_match=9 is the default/legacy assessment — the most common value in the table (350 of 910 entries). My extension consistently gets the legacy assessment.

SystemPolicy object_state

The object_state table confirms both my app and Tailscale are recognized as "Notarized Developer ID" (authority 11) at the app bundle level. The problem is specifically at the extension level.

Hypothesis

stapler staple writes the top-level app CDHash as a direct entry in tickets but only records nested component CDHashes (including the system extension) in the hashes table. If sysextd's policy evaluation looks up the extension's CDHash only in tickets and not hashes, it would fail to find the notarization ticket and fall back to the legacy Developer ID assessment — which would explain the "no policy" rejection.

Tailscale's extension works because it has a direct tickets entry, likely created when it was first activated on a pre-Tahoe macOS version.

`sysextd` rejects new `NEFilterDataProvider` activation with "no policy" on macOS 26 — despite valid Developer ID + notarization
 
 
Q