I've implemented a custom VPN system extension for macOS, utilizing Packet Tunnel Provider.
One of the users reported a problem: he was connected to the VPN, and then his Mac entered sleep mode. Upon waking, the VPN is supposed to connect automatically (because of the on-demand rules).
The VPN's status changed to 'connecting', but it remained stuck in this status.
From my extension logs, I can see that the 'startTunnelWithOption()' function was called 2 minutes after the user clicked the 'connect' button.
From the system logs, I noticed some 'suspicious' logs, but I can't be sure if they are related to the problem. Some of them are:
kernel: (Sandbox) Sandbox: nesessionmanager(562) deny(1) system-fsctl (_IO "h" 47)
entitlement com.apple.developer.endpoint-security.client not present or not true (I don't need this entitlement at the extension)
nesessionmanager: [com.apple.networkextension:] NESMVPNSession[Primary Tunnel:XXXXXX(null)]: Skip a start command from YYYYY:session in state connecting
NetworkExtension.com.***: RunningBoard doesn't recognize submitted process - treating as a anonymous process
sysextd: activateDecision found existing entry of same version: state activated_enabled, ID FAE...
Are any of the logs related to the above problem? How can I debug such issues? What info should I get from the user?
Networking
RSS for tagExplore the networking protocols and technologies used by the device to connect to Wi-Fi networks, Bluetooth devices, and cellular data services.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
I'm currently developing an iOS app with image upload functionality.
To enhance upload speed, I'm considering implementing parallel uploads using Swift’s TaskGroup.
However, I have concerns that in environments with limited bandwidth, parallelization might introduce overhead and contention, ultimately slowing down uploads instead of improving them.
Specifically, I'm curious about:
Is this concern valid? Does parallelizing uploads become counterproductive in low-bandwidth conditions due to overhead and network contention?
If so, I'm considering dynamically adjusting the concurrency level based on network conditions. Does anyone have experience or best practices regarding such an approach?
Any insights or advice would be greatly appreciated.
Thank you!
Hi, I had a few questions regarding the multicast networking entitlement.
What are the criteria for approval?
Do ad-hoc multicast protocols fall under the approval criteria?
How long do approvals for multicasting generally take?
1、已经检查过手机的存储空间,还有一百多G的空间。app端进行网络接口情况的时候报错了,报错信息如下:
Error : Error Domain=NSPOSIXErrorDomain Code=28 "No space left on device" UserInfo={_NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <7DB1CBFD-B9BE-422D-9C9A-78D8FC04DC1B>.<76>, _kCFStreamErrorDomainKey=1, _kCFStreamErrorCodeKey=28, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <7DB1CBFD-B9BE-422D-9C9A-78D8FC04DC1B>.<76>"
), _NSURLErrorNWPathKey=satisfied (Path is satisfied), interface: pdp_ip0[lte], ipv4, ipv6, dns, expensive, estimated upload: 65536Bps, uses cell}
2、手机型号是iPhone 15 Plus,iOS 17.6.1
Topic:
App & System Services
SubTopic:
Networking
There are multiple report of crashes on URLConnectionLoader::loadWithWhatToDo. The crashed thread in the stack traces pointing to calls inside CFNetwork which seems to be internal library in iOS.
The crash has happened quite a while already (but we cannot detect when the crash started to occur) and impacted multiple iOS versions recorded from iOS 15.4 to 18.4.1 that was recorded in Xcode crash report organizer so far.
Unfortunately, we have no idea on how to reproduce it yet but the crash keeps on increasing and affect more on iOS 18 users (which makes sense because many people updated their iOS to the newer version) and we haven’t found any clue on what actually happened and how to fix it on the crash reports. What we understand is it seems to come from a network request that happened to trigger the crash but we need more information on what (condition) actually cause it and how to solve it.
Hereby, I attach sample crash report for both iOS 15 and 18.
I also have submitted a report (that include more crash reports) with number: FB17775979.
Will appreciate any insight regarding this issue and any resolution that we can do to avoid it.
iOS 15.crash
iOS 18.crash
Question 1: After NetworkExtension is installed, when the software receives a pushed uninstall command, it needs to download the entire software but fails to uninstall this NetworkExtension. Are there any solutions?
Question 2: How can residual, uninstalled NetworkExtensions be cleaned up when SIP (System Integrity Protection) is enabled?
Our application currently uses NEFilterPacketProvider to filter network traffic based on Layer 4 rules (5-tuple: source IP, destination IP, source port, destination port, and protocol) on a packet-by-packet basis.
We now want to extend this filtering to also consider the associated process—for example, allowing traffic from a specific source IP to a destination IP and port only if it's associated with a specific local process. That is, we’d like to make filtering decisions not just based on the 5-tuple, but also on the identity of the process either sending or receiving the traffic.
We’ve looked into NEFilterSocketProvider, which does expose Layer 7 information such as process identifiers. However, it doesn’t seem to be tightly synchronized with the packet flow handled by NEFilterPacketProvider. As a result, there’s a risk that we might only get process information after the TCP handshake is complete, or before the socket is fully bound—at which point some of the 5-tuple fields (such as the local port) may still be unavailable.
What we need is a way to correlate the 5-tuple with the relevant process name (either sender or receiver) at the time the first packet—e.g., a SYN packet—is about to be sent or received.
Is there a recommended way to achieve this kind of early, process-aware filtering using NetworkExtension APIs?
Hi all!
I’m having trouble distributing an iOS app with a DNS Proxy NetworkExtension via AdHoc. The app and extension work perfectly with development profiles, but when I export and install the AdHoc IPA, I get a “permission denied” error when trying to install/enable the DNS Proxy extension.
What I’ve done:
Both the app and the DNS Proxy extension have their own App IDs in the Apple Developer portal.
Both App IDs have the same App Group enabled: group.com.irakai.SafeLinkApp2.
The extension App ID has the NetworkExtension capability with dns-proxy enabled.
I created two AdHoc provisioning profiles (one for the app, one for the extension), both including the same devices and the correct entitlements.
I assigned the correct AdHoc profiles to each target in Xcode and exported the IPA via Organizer.
I install the IPA on a registered device using Apple Configurator.
Entitlements (extracted from the signed binaries on device):
App:
<key>application-identifier</key><string>6PBG234246.com.irakai.SafeLinkApp2</string>
<key>com.apple.developer.networking.networkextension</key><array>
<string>packet-tunnel-provider</string>
<string>dns-proxy</string>
</array>
<key>com.apple.developer.team-identifier</key><string>6PBG234246</string>
<key>com.apple.security.application-groups</key><array>
<string>group.com.irakai.SafeLinkApp2</string>
</array>
<key>get-task-allow</key><false/>
DNSProxy Extension:
<key>application-identifier</key><string>6PBG234246.com.irakai.SafeLinkApp2.DNSProxy</string>
<key>com.apple.developer.networking.networkextension</key><array>
<string>dns-proxy</string>
</array>
<key>com.apple.developer.team-identifier</key><string>6PBG234246</string>
<key>com.apple.security.application-groups</key><array>
<string>group.com.irakai.SafeLinkApp2</string>
</array>
<key>get-task-allow</key><false/>
Error message (from my app’s logs):
Error instalando DNS Proxy: permission denied
Usuario: Roberto
AppGroup: group.com.irakai.SafeLinkApp2
AppGroupPath: /private/var/mobile/Containers/Shared/AppGroup/D8AD2DED-AD96-4915-9B7A-648C9504679B
Entitlements:
BundleId: com.irakai.SafeLinkApp2
Debug info: Error Domain=NEDNSProxyErrorDomain Code=1 "permission denied" UserInfo={NSLocalizedDescription=permission denied}
Other details:
The device is included in both AdHoc profiles.
The App Group is present and identical in both entitlements.
The extension’s bundle identifier matches the App ID in the portal.
The extension is signed with the correct AdHoc profile.
I have tried rebooting the device and reinstalling the IPA.
The error only occurs with AdHoc; development builds work fine.
Questions:
Is there anything else I should check regarding AdHoc provisioning for NetworkExtension DNS Proxy?
Are there any known issues with AdHoc and NetworkExtension on recent iOS versions?
Is there a way to get more detailed diagnostics from the system about why the permission is denied?
Could this be a bug in iOS, or am I missing a subtle configuration step?
Any help or suggestions would be greatly appreciated.
Thank you!
Goal : Block all outbound connections to a static list of hosts (both In-app requests and WKWebView/Safari).
App & both extensions have Network Extension entitlement with content-filter-provider and filter-control-provider
What’s working:
Safari and WKWebView requests matching the block list are dropped.
What’s broken:
In-app traffic never reaches the Data Provider—those requests always succeed.
Setup:
• NEFilterProviderConfiguration with both Data & Control providers, filterBrowsers = true, filterSockets = true
• Data Provider implements handleNewFlow for socket/browser flows
• Control Provider implements handleNewFlow for browser flows
• Enabled via saveToPreferences() and toggled ON in Settings
I'm working on enabling a content filter in my iOS app using NEFilterManager and NEFilterProviderConfiguration. The setup works perfectly in debug builds when running via Xcode, but fails on TestFlight builds with the following error:
**Failed to save filter settings: permission denied
**
**Here is my current implementation:
**
(void)startContentFilter {
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults synchronize];
[[NEFilterManager sharedManager] loadFromPreferencesWithCompletionHandler:^(NSError * _Nullable error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
NSLog(@"Failed to load filter: %@", error.localizedDescription);
[self showAlertWithTitle:@"Error" message:[NSString stringWithFormat:@"Failed to load content filter: %@", error.localizedDescription]];
return;
}
NEFilterProviderConfiguration *filterConfig = [[NEFilterProviderConfiguration alloc] init];
filterConfig.filterSockets = YES;
filterConfig.filterBrowsers = YES;
NEFilterManager *manager = [NEFilterManager sharedManager];
manager.providerConfiguration = filterConfig;
manager.enabled = YES;
[manager saveToPreferencesWithCompletionHandler:^(NSError * _Nullable error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
NSLog(@"Failed to save filter settings: %@", error.localizedDescription);
[self showAlertWithTitle:@"Error" message:[NSString stringWithFormat:@"Failed to save filter settings: %@", error.localizedDescription]];
} else {
NSLog(@"Content filter enabled successfully!");
[self showAlertWithTitle:@"Success" message:@"Content filter enabled successfully!"];
}
});
}];
});
}];
}
**What I've tried:
**
Ensured the com.apple.developer.networking.networkextension entitlement is set in both the app and system extension.
The Network extension target includes content-filter-provider.
Tested only on physical devices.
App works in development build, but not from TestFlight.
**My questions: **
Why does saveToPreferencesWithCompletionHandler fail with “permission denied” on TestFlight?
Are there special entitlements required for using NEFilterManager in production/TestFlight builds?
Is MDM (Mobile Device Management) required to deploy apps using content filters?
Has anyone successfully implemented NEFilterProviderConfiguration in production, and if so, how?
Topic:
App & System Services
SubTopic:
Networking
Tags:
Extensions
Swift
Network Extension
Objective-C
I need to know the https address of a certain page within my app. This is going to be used as a redirect URL. I don't think it is a good idea to use deep links because it has to be an https address. I don't think Universal Links will work because it is not my website that I will be communicating with.
Recently, we have observed that after upgrading to OS 15.4.1, some devices are experiencing network issues.
We are using a Network Extension with a transparent app proxy in our product. The user encounters this issue while using our client, but the issue persists even after stopping the client app.
This appears to be an OS issue.
Below is the sytem logs.
In the system logs, it says [C669.1 Hostname#546597df:443 failed transform (unsatisfied (No network route), flow divert agg: 2)] event: transform:children_failed @0.001s
In scutil --dns, it says not reachble.
DNS configuration
resolver #1
flags :
reach : 0x00000000 (Not Reachable)
resolver #2
domain : local
options : mdns
timeout : 5
flags :
reach : 0x00000000 (Not Reachable)
order : 300000
resolver #3
domain : 254.169.in-addr.arpa
options : mdns
timeout : 5
flags :
reach : 0x00000000 (Not Reachable)
order : 300200
resolver #4
domain : 8.e.f.ip6.arpa
options : mdns
timeout : 5
flags :
reach : 0x00000000 (Not Reachable)
order : 300400
resolver #5
domain : 9.e.f.ip6.arpa
options : mdns
timeout : 5
flags :
reach : 0x00000000 (Not Reachable)
order : 300600
resolver #6
domain : a.e.f.ip6.arpa
options : mdns
timeout : 5
flags :
reach : 0x00000000 (Not Reachable)
order : 300800
resolver #7
domain : b.e.f.ip6.arpa
options : mdns
timeout : 5
flags :
reach : 0x00000000 (Not Reachable)
order : 301000
We need to restart the system to recover from the issue.
Hi!
I'm working on a solution (iOS 18) that uses Network Extensions PacketTunnelProvider and Content Filter. Currently I'm trying to integrate it with another extension – DNSProxyProvider. My goal is to process dns queries and use resolved ips and names for additional routing inside of the packet tunnel. I'm running into a major issue: whenever both VPN and DNS proxy are active simultaneously, the device completely loses internet connectivity — no traffic goes through, and DNS resolution seems to stop working entirely.
I know about the mdm supervision requirement to use DNSProxyProvider and that's covered as I work with a managed device and install a DNS proxy profile, here's how its .mobileconfig file looks like:
The DNS proxy itself works fine when working by itself (without VPN being turned on), as I implemented it that it successfully processes DNS packets flows while collecting information about domains etc, and everything works perfectly. Problems begin when using VPN at the same time. I'm aware that tunnel settings include dns related options that can affect this, but I haven't had much luck with tweaking them. Here's how they look right now for reference:
let settings: NEPacketTunnelNetworkSettings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: "240.0.0.1")
// let dnsSettings = NEDNSSettings(servers: "8.8.8.8,8.8.4.4".components(separatedBy: ","))
// dnsSettings.matchDomains = [""]
// settings.dnsSettings = dnsSettings
settings.proxySettings = nil
/* ipv4 settings */
let ipv4Settings = NEIPv4Settings(addresses: ["240.0.0.2"], subnetMasks: ["255.255.255.0"])
ipv4Settings.includedRoutes = [NEIPv4Route.default()]
settings.ipv4Settings = ipv4Settings
/* MTU */
settings.mtu = 1500
return settings
I've tried excluding some dns related ip routes and dns settings shenanigans but nothing.
I haven't found any information that might suggest that using both of these extensions at the same time doesn't work, on the contrary, this page in the official documentation about the expected use of packet tunnel provider the expected use of packet tunnel provider, as it talks about the fact that you should not use it for interception of all of DNS traffic, as the use of DNSPRoxyProvider (or dns settings) are built for that, which in my mind, suggests that there should be no problem with using them both and just splitting the dns traffic handling to the proxy.
Will be thankful for any help!
Hello, I have encountered an issue with an iPhone 15PM with iOS 18.5. The NSHTTPCookieStorage failed to clear cookies, but even after clearing them, I was still able to retrieve them. However, on the same system
It is normal on iPhone 14PM. I would like to know the specific reason and whether there are any adaptation related issues. Following code:
NSHTTPCookie *cookie;
NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (cookie in [storage cookies]) {
[storage deleteCookie:cookie];
}
We are implementing a connection between iPad and iPhone devices using LocalPushConnectivity,
and have introduced SimplePushProvider into the project.
We will have it switch between roles of Server and Client within a single project.
※ iPad will be Server and the iPhone will be Client.
Communication between Server and Client is via TLS, with Server reading p12 file and Client setting public key.
Currently, a TLS error code of "-9836" (invalid protocol version) is occurring when communicating from Client's SimplePushProvider to Server.
I believe that Client is sending TLS1.3, and Server is set to accept TLS1.2 to 1.3.
Therefore, I believe that the actual error is not due to TLS protocol version, but is an error that is related to security policy or TLS communication setting.
Example:
P12 file does not meet some requirement
NWProtocolTLS.Options setting is insufficient
etc...
I'm not sure what the problem is, so please help.
For reference, I will attach you implementation of TLS communication settings.
P12 file is self-signed and was created by exporting it from Keychain Access.
Test environment:
iPad (OS: 16.6)
iPhone (OS: 18.3.2)
ConnectionOptions: TLS communication settings
public enum ConnectionOptions {
public enum TCP {
public static var options: NWProtocolTCP.Options {
let options = NWProtocolTCP.Options()
options.noDelay = true
options.enableFastOpen
return options
}
}
public enum TLS {
public enum Error: Swift.Error {
case invalidP12
case unableToExtractIdentity
case unknown
}
public class Server {
public let p12: URL
public let passphrase: String
public init(p12 url: URL, passphrase: String) {
self.p12 = url
self.passphrase = passphrase
}
public var options: NWProtocolTLS.Options? {
guard let data = try? Data(contentsOf: p12) else {
return nil
}
let pkcs12Options = [kSecImportExportPassphrase: passphrase]
var importItems: CFArray?
let status = SecPKCS12Import(data as CFData, pkcs12Options as CFDictionary, &importItems)
guard status == errSecSuccess,
let items = importItems as? [[String: Any]],
let importItemIdentity = items.first?[kSecImportItemIdentity as String],
let identity = sec_identity_create(importItemIdentity as! SecIdentity)
else {
return nil
}
let options = NWProtocolTLS.Options()
sec_protocol_options_set_min_tls_protocol_version(options.securityProtocolOptions, .TLSv12)
sec_protocol_options_set_max_tls_protocol_version(options.securityProtocolOptions, .TLSv13)
sec_protocol_options_set_local_identity(options.securityProtocolOptions, identity)
sec_protocol_options_append_tls_ciphersuite(options.securityProtocolOptions, tls_ciphersuite_t.RSA_WITH_AES_128_GCM_SHA256)
return options
}
}
public class Client {
public let publicKeyHash: String
private let dispatchQueue = DispatchQueue(label: "ConnectionParameters.TLS.Client.dispatchQueue")
public init(publicKeyHash: String) {
self.publicKeyHash = publicKeyHash
}
// Attempt to verify the pinned certificate.
public var options: NWProtocolTLS.Options {
let options = NWProtocolTLS.Options()
sec_protocol_options_set_min_tls_protocol_version(options.securityProtocolOptions, .TLSv12)
sec_protocol_options_set_max_tls_protocol_version(options.securityProtocolOptions, .TLSv13)
sec_protocol_options_set_verify_block(
options.securityProtocolOptions,
verifyClosure,
dispatchQueue
)
return options
}
private func verifyClosure(
secProtocolMetadata: sec_protocol_metadata_t,
secTrust: sec_trust_t,
secProtocolVerifyComplete: @escaping sec_protocol_verify_complete_t
) {
let trust = sec_trust_copy_ref(secTrust).takeRetainedValue()
guard let serverPublicKeyData = publicKey(from: trust) else {
secProtocolVerifyComplete(false)
return
}
let keyHash = cryptoKitSHA256(data: serverPublicKeyData)
guard keyHash == publicKeyHash else {
// Presented certificate doesn't match.
secProtocolVerifyComplete(false)
return
}
// Presented certificate matches the pinned cert.
secProtocolVerifyComplete(true)
}
private func cryptoKitSHA256(data: Data) -> String {
let rsa2048Asn1Header: [UInt8] = [
0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00
]
let data = Data(rsa2048Asn1Header) + data
let hash = SHA256.hash(data: data)
return Data(hash).base64EncodedString()
}
private func publicKey(from trust: SecTrust) -> Data? {
guard let certificateChain = SecTrustCopyCertificateChain(trust) as? [SecCertificate],
let serverCertificate = certificateChain.first else {
return nil
}
let publicKey = SecCertificateCopyKey(serverCertificate)
return SecKeyCopyExternalRepresentation(publicKey!, nil)! as Data
}
}
}
}
Hello there,
Starting from iOS 18.4, support was included for QWAC Validation and QCStatements.
Using the official QWAC Validator at: https://eidas.ec.europa.eu/efda/qwac-validation-tool
I was able to check that the domain "eidas.ec.europa.eu" has a valid QWAC certificate. However, when trying to obtain the same result using the new API, I do not obtain the same result.
Here is my sample playground code:
import Foundation
import Security
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
@MainActor
class CertificateFetcher: NSObject, URLSessionDelegate {
private let url: URL
init(url: URL) {
self.url = url
super.init()
}
func start() {
let session = URLSession(configuration: .ephemeral, delegate: self, delegateQueue: nil)
let task = session.dataTask(with: url) { data, response, error in
if let error = error {
print("Error during request: \(error)")
} else {
print("Request completed.")
}
}
task.resume()
}
nonisolated func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
guard let trust = challenge.protectionSpace.serverTrust else {
completionHandler(.cancelAuthenticationChallenge, nil)
return
}
if let certificates = SecTrustCopyCertificateChain(trust) as? [SecCertificate] {
self.checkQWAC(certificates: certificates)
}
let credential = URLCredential(trust: trust)
completionHandler(.useCredential, credential)
}
nonisolated func checkQWAC(certificates: [SecCertificate]) {
let policy = SecPolicyCreateSSL(true, nil)
var trust: SecTrust?
guard SecTrustCreateWithCertificates(certificates as CFArray, policy, &trust) == noErr, let trust else {
print("Unable to create SecTrust")
return
}
var error: CFError?
guard SecTrustEvaluateWithError(trust, &error) else {
print("Trust evaluation failed")
return
}
guard let result = SecTrustCopyResult(trust) as? [String : Any] else {
print("No result dictionary")
return
}
let qwacStatus = result[kSecTrustQWACValidation as String]
let qcStatements = result[kSecTrustQCStatements as String]
print("QWAC Status: \(String(describing: qwacStatus))")
print("QC Statements: \(String(describing: qcStatements))")
}
}
let url = URL(string: "https://eidas.ec.europa.eu/")!
let fetcher = CertificateFetcher(url: url)
fetcher.start()
Which prints:
QWAC Status: nil
QC Statements: nil
Request completed.
Am I making a mistake while using the Security framework? I would greatly appreciate any help or guidance you can provide.
As a third-party application on Apple Watch, can it be located in the same LAN httpServer? Currently, when testing to initiate an http request in the LAN, the connection timeout is returned, code: -1001
self.customSession.request("http://10.15.48.191:9000/hello").response { response in
switch response.result {
case .success(let data):
dlog("✅ 请求成功,收到数据:")
if let html = String(data: data ?? Data(), encoding: .utf8) {
dlog(html)
}
case .failure(let error):
dlog("❌ 请求失败:\(error.localizedDescription)")
}
}
执行后报错
Task <B71BE820-FD0E-4880-A6DD-1F8F6EAF98B0>.<1> finished with error [-1001] Error Domain=NSURLErrorDomain Code=-1001 "请求超时。" UserInfo={_kCFStreamErrorCodeKey=-2102, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <B71BE820-FD0E-4880-A6DD-1F8F6EAF98B0>.<1>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <B71BE820-FD0E-4880-A6DD-1F8F6EAF98B0>.<1>",
"LocalDataPDTask <B71BE820-FD0E-4880-A6DD-1F8F6EAF98B0>.<1>",
"LocalDataTask <B71BE820-FD0E-4880-A6DD-1F8F6EAF98B0>.<1>"
), NSLocalizedDescription=请求超时。, _kCFStreamErrorDomainKey=4, NSErrorFailingURLStringKey=http://10.15.48.191:9000/hello, NSErrorFailingURLKey=http://10.15.48.191:9000/hello}
i unfortunatly upgraded to Sequoia since then I see when:
i select
XCode ->Product->run
i see
Error: No route to host
i cannot grant access to local network for XCode
i can no longer debug my program as i did with Sonora
On one test machine, our extension wouldn't load, because [NETransparentProxyManager loadAllFromPreferencesWithCompletionHandler] can't find a manager, saying Skipping configuration appname because it is of the wrong type. This is the first time I've seen this behaviour.
(The containing app tries to find a configuration, if it can't find it it creates one, then modifies whatever it found or created, then stores it. I don't have the right logging yet for that, so I can't see the error messages. [NSLog instead of os_log_error.])
We are a hardware manufacturer. Our devices are connected via Ethernet to Mac mini systems, where our custom macOS application is installed and communicates with the connected hardware. The application is signed and deployed as a standard application bundle.
Description
The application performs a UDP broadcast using the Universal Plug and Play (UPnP) discovery mechanism to locate devices connected to the same local network segment.
We have observed a reproducible issue with macOS 15.x (confirmed with 15.1 through 15.4), where the discovery fails under specific circumstances. The behavior is as follows:
If the application is launched via Finder (e.g., double-clicked by the user), no device is discovered.
If the same binary is launched from the Terminal, discovery works as expected and the connected device is found.
Downgrading the affected Mac mini to macOS 14.x (e.g., Sonoma 14.0 or 14.1) restores the expected behavior—discovery works via Finder as well.
The issue is observed only on Intel-based Mac minis.
On Apple Silicon (ARM-based) Mac minis, the discovery via Finder works correctly, even on macOS 15.4.
What we know
The problem is tied to how the network stack or sandboxing behaves when the application is launched via Finder.
There are no visible error messages.
It is unclear whether the broadcast packet is being blocked, or if the response from the device is dropped or filtered by the system.
Reproduction Steps
Install our signed application bundle on a Mac mini (Intel).
Connect our device via Ethernet to the Mac mini.
Launch the application via Finder – the device is not found.
Quit the application.
Launch the same binary from Terminal – the device is correctly discovered.
Downgrade the same system to macOS 14.x – discovery works in both cases (Finder and Terminal).
Upgrade to macOS 15.x – the issue reappears.
Technical Details
macOS Version(s) Affected: 15.x (confirmed with 15.1 through 15.4),
Mac mini Model: Intel-based Mac minis
Type of Communication: UDP broadcast using UPnP
Reproducibility: 100% reproducible with affected macOS versions.
Software Environment: Custom application developed by us, running as a user-space application under standard macOS network APIs.
No Issues: When the same setup is used on earlier macOS versions.
Request
Can you confirm whether this is expected behavior due to changes in macOS 15 (e.g., sandboxing, entitlements, network permissions)?
What steps or configuration changes are required to ensure UDP discovery works again when the application is launched via Finder?
Are there relevant macOS logs (e.g., Console, system logs) we can inspect for network-related blocks or errors?
We would appreciate any guidance or clarification on how to adapt our application or system configuration to restore expected network discovery behavior.
Thank you in advance for your support!