Hi, We are trying to use Apple Security API for KeyChain Services.
Using the common App Group : Specifying the common app group in the "kSecAttrAccessGroup" field of the KeyChain query, allowed us to have a shared keychains for different apps (targets) in the app group, but this did not work for extensions.
Enabling the KeyChain Sharing capability : We enabled the KeyChain Sharing Ability in the extensions and the app target as well, giving a common KeyChain Access group. Specifying this in the kSecAttrAccessGroup field also did not work. This was done in XCode as we were unable to locate it in the Developer portal in Indentifiers.
We tried specifying "$AppIdentifier.KeyChainSharingGroup" in the kSecAttrAccessGroup field , but this did not work as well
The error code which we get in all these 3 cases when trying to access the Keychain from the extension is error code 25291 (errSecNotAvailable). The Documentation says this error comes when "No Trust Results are available" and printing the error in xcode using the status says "No keychain is available.
The online Documentation says that it is possible to share keychain with extensions, but by far we are unable to do it with the methods suggested.
Do we need any special entitlement for this or is there something we are missing while using these APIs?
We really appreciate any and all help in solving this issue!
Thank you
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
Created
Hi,
I’m using Network Framework to implement a UDP client via NWConnection, and I’m looking for clarification about the correct and fully safe shutdown procedure, especially regarding resource release.
I have initiated some pending receive calls on the NWConnection (using receive). After calling connection.cancel(), do we need to wait for the cancellation of these pending receives?
As mentioned in this thread, NWConnection retains references to the receive closures and releases them once they are called. If a receive closure holds a reference to the NWConnection itself, do we need to wait for these closures to be called to avoid memory leaks? Or, if there are no such retained references, we don't need to wait for the cancellation of the pending I/O and cancelled state for NWConnection?
Hi,
I’m using Network Framework to implement a UDP listener via NWListener. I am looking for clarification about the correct and fully safe shutdown procedure, especially regarding resource release.
After calling listener.cancel(), do we need to wait for the .cancelled state before exiting the application? Or can we just exit once the cancellation is initiated, assuming the OS will close the NWListener and there will be no resource leak?
Is it recommended (or required) to set newConnectionHandler = nil when shutting down a UDP listener?
My understanding is that if there is no NWListener attached, then whenever a connection is accepted by the OS, it will not be delivered to the application and the OS will simply drop it.
Summary
NetworkConnection<WebSocket> in iOS 26 Network framework throws POSIXErrorCode(rawValue: 22): Invalid argument when receiving WebSocket ping (opcode 9) or pong (opcode 10) control frames. This prevents proper WebSocket keep-alive functionality.
Environment
iOS 26.0 (Simulator)
macOS 26.1
Xcode 26.0
Note: This issue was initially discovered on iOS 26 Simulator. The same behavior was confirmed on macOS 26, suggesting a shared bug in the Network framework. The attached sample code is for macOS for easier reproduction.
Description
When using the new NetworkConnection<WebSocket> API introduced in iOS 26 or macOS 26, the receive() method throws EINVAL error whenever a ping or pong control frame is received from the server.
This is a critical issue because:
WebSocket servers commonly send ping frames to keep connections alive
Clients send ping frames to verify connection health
The receive callback never receives the ping/pong frame - the error occurs before the frame reaches user code
Steps to Reproduce
Create a WebSocket connection to any server that supports ping/pong (e.g., wss://echo.websocket.org):
import Foundation
import Network
// MARK: - WebSocket Ping/Pong EINVAL Bug Reproduction
// This sample demonstrates that NetworkConnection<WebSocket> throws EINVAL
// when receiving ping or pong control frames.
@main
struct WebSocketPingPongBug {
static func main() async {
print("=== WebSocket Ping/Pong EINVAL Bug Reproduction ===\n")
do {
try await testPingPong()
} catch {
print("Test failed with error: \(error)")
}
}
static func testPingPong() async throws {
let host = "echo.websocket.org"
let port: UInt16 = 443
print("Connecting to wss://\(host)...")
let endpoint = NWEndpoint.hostPort(
host: NWEndpoint.Host(host),
port: NWEndpoint.Port(rawValue: port)!
)
try await withNetworkConnection(to: endpoint, using: {
WebSocket {
TLS {
TCP()
}
}
}) { connection in
print("Connected!\n")
// Start receive loop in background
let receiveTask = Task {
var messageCount = 0
while !Task.isCancelled {
do {
let (data, metadata) = try await connection.receive()
messageCount += 1
print("[\(messageCount)] Received frame - opcode: \(metadata.opcode)")
if let text = String(data: data, encoding: .utf8) {
print("[\(messageCount)] Content: \(text)")
} else {
print("[\(messageCount)] Binary data: \(data.count) bytes")
}
} catch let error as NWError {
if case .posix(let code) = error, code == .EINVAL {
print("❌ EINVAL error occurred! (POSIXErrorCode 22: Invalid argument)")
print(" This is the bug - ping/pong frame caused EINVAL")
// Continue to demonstrate workaround
continue
}
print("Receive error: \(error)")
break
} catch {
print("Receive error: \(error)")
break
}
}
}
// Wait for initial message from server
try await Task.sleep(for: .seconds(2))
// Test 1: Send text message (should work)
print("\n--- Test 1: Sending text message ---")
try await connection.send("Hello, WebSocket!")
print("✅ Text message sent")
try await Task.sleep(for: .seconds(1))
// Test 2: Send ping (pong response will cause EINVAL)
print("\n--- Test 2: Sending ping frame ---")
print("Expecting EINVAL when pong is received...")
let pingMetadata = NWProtocolWebSocket.Metadata(opcode: .ping)
try await connection.ping(Data()) {
pingMetadata
}
print("✅ Ping sent, waiting for pong...")
// Wait for pong response
try await Task.sleep(for: .seconds(2))
// Cleanup
receiveTask.cancel()
print("\n=== Test Complete ===")
print("If you saw 'EINVAL error occurred!' above, the bug is reproduced.")
}
}
}
The receive() call fails with error when pong arrives:
❌ EINVAL error occurred! (POSIXErrorCode 22: Invalid argument)
Test Results
Scenario
Result
Send/receive text (opcode 1)
✅ OK
Client sends ping, receives pong
❌ EINVAL on pong receive
Expected Behavior
The receive() method should successfully return ping and pong frames, or at minimum, handle them internally without throwing an error. The autoReplyPing option should allow automatic pong responses without disrupting the receive loop.
Actual Behavior
When a ping or pong control frame is received:
The receive() method throws NWError.posix(.EINVAL)
The frame never reaches user code (no opcode check is possible)
The connection remains valid, but the receive loop is interrupted
Workaround
Catch the EINVAL error and restart the receive loop:
while !Task.isCancelled {
do {
let received = try await connection.receive()
// Process message
} catch let error as NWError {
if case .posix(let code) = error, code == .EINVAL {
// Control frame caused EINVAL, continue receiving
continue
}
throw error
}
}
This workaround allows continued operation but:
Cannot distinguish between ping-related EINVAL and other EINVAL errors
Cannot access the ping/pong frame content
Cannot implement custom ping/pong handling
Impact
WebSocket connections to servers that send periodic pings will experience repeated EINVAL errors
Applications must implement workarounds that may mask other legitimate errors
Additional Information
Packet capture confirms ping/pong frames are correctly transmitted at the network level
The error occurs in the Network framework's internal processing, before reaching user code
Hello,
I have an app that is using iOS 26 Network Framework APIs.
It is using QUIC, TLS 1.3 and Bonjour. For TLS I am using a PKCS#12 identity.
All works well and as expected if the devices (iPhone with no cellular, iPhone with cellular, and iPad no cellular) are all on the same wifi network.
If I turn off my router (ie no more wifi network) and leave on the wifi toggle on the iOS devices - only the non cellular iPhone and iPad are able to discovery and connect to each other. My iPhone with cellular is not able to.
By sharing my logs with Cursor AI it was determined that the connection between the two problematic peers (iPad with no cellular and iPhone with cellular) never even makes it to the TLS step because I never see the logs where I print out the certs I compare.
I tried doing "builder.requiredInterfaceType(.wifi)" but doing that blocked the two non cellular devices from working. I also tried "builder.prohibitedInterfaceTypes([.cellular])" but that also did not work.
Is AWDL on it's way out? Should I focus my energy on Wi-Fi Aware?
Regards,
Captadoh
I am working on a game app that uses multicast to advertise and locate a hosted game. It therefore requires local network permission. Entitlements are set up correctly in the app for using multicast.
I have two iPhones I use for testing my app, one was using iOS 18.1.x (not exactly sure about the value of x) and the other was using a later version of 18. I install the app on these devices via TestFlight. On the device using iOS 18.1.x the networking worked perfectly, and I could host or join a game (connecting to the same app running on my mac).
The device using the later version would fail to see advertised games as well as failing to advertise games itself. Updating this device to the latest iOS (18.7.2) did not fix the problem. To test that it is likely related to the later version of iOS, I updated the 18.1.x device that was working to 18.7.2, and now it does not work either.
I could see the app listed under "Privacy and Security/Local Network" in settings on the device that used to work with 18.1.x, but not the device with the later version of iOS . Now it does not show up on either device. Nor does either device ask for permission when I activate a network game on the app, even after repeatedly deleting and reinstalling the app as well as resetting the devices.
Why does the device not ask for permission when I try to set up a network game, and how can I get this working again?
Topic:
App & System Services
SubTopic:
Networking
Hello to all
I have coded in swift a headless app, that launches 3 go microservices and itself. The app listens via unix domain sockets for commands from the microservices and executes different VPN related operations, using the NEVPNManager extension. Because there are certificates and VPN operations, the headless app and two Go microservices must run as root.
The app and microservices run perfectly when I run in Xcode launching the swift app as root. However, I have been trying for some weeks already to modify the application so at startup it requests the password and runs as root or something similar, so all forked apps also run as root. I have not succeeded. I have tried many things, the last one was using SMApp but as the swift app is a headless app and not a CLI command app it can not be embedded. And CLI apps can not get the VPN entitlements. Can anybody please give me some pointers how can I launch the app so it requests the password and runs as root in background or what is the ideal framework here? thank you again.
Hi,
I played around the last days with the new NetworkConnection API from Network framework that supports structured concurrency. I discovered a behavior, which is unexpected from my understanding.
Let's say you have a dead endpoint or something that does not exist. Something where you receive a noSuchRecord error. When I then try to send data, I would expect that the send function throws an error but this does not happen. The function now suspends indefinitely which is well not a great behavior.
Example simplified:
func send() async {
let connection = NetworkConnection(to: .hostPort(host: "apple.co.com", port: 8080)) {
TCP()
}
do {
try await connection.send("Hello World!".raw)
} catch {
print(error)
}
}
I'm not sure if this is the intended behavior or how this should be handled.
Thanks and best regards,
Vinz
We are developing an enterprise app that connects to a local server.
It uses simple URLSessions. There is a view in the app where you enter the server url (IP address) and a connection check is made.
iOS asks for permission to access the local network.
Everything works. If the server is reachable, the connection info is saved.
Recently we encountered a very strange issue:
We also have a beta version of this app.
If we first install the normal version on a device, enter the server IP, save, and then install the beta version and do the same there: It does not get a connection (it waits for the timeout).
The strange part is: If I try to configure the connection in the normal version again, it also does not work, it just waits for the timeout.
The really strange part: When I delete the beta version, while the normal version is waiting for its connection, the connection succeeds immediately.
Both versions have a different display name, bundle id.
I also tried using a device that is not in our MDM: same problem.
Even the iOS version seems to have no impact: I tried on iOS 15, 18 and 26.
Is there an explanation and hopefully also a solution to this problem?
Topic:
App & System Services
SubTopic:
Networking
I've noticed that if a call to startVPNTunnel() is made while no network interface is active on the system, the call "succeeds" (i.e., doesn't throw), but the VPN connection state goes straight from NEVPNStatus.disconnecting to NEVPNStatus.disconnected.
The docs for startVPNTunnel() state:
In Swift, this method returns Void and is marked with the throws keyword to indicate that it throws an error in cases of failure.
Additionally, there is an NEVPNConnectionError enum that contains a noNetworkAvailable case. However, this isn't thrown in this case, when startVPNTunnel() is called.
I just wanted to ask under what circumstances startVPNTunnel() does throw, and should this be one of them?
Additionally, to catch such errors, would it be better to call fetchLastDisconnectError() in the .NEVPNStatusDidChange handler?
After dropping an A-record TTL to 60 secs (it was previously no higher than 600 secs for several weeks) and making an IP change for a small business website on Monday, I took down the old web service just over 24 hours later on Tuesday evening. We then had reports of some customers not being able to access the website on Wednesday morning. On investigation using my iPhone it would appear that Apple Private Relay is still directing clients to the old IP address.
It's just as well I have iCloud+ as I would never have seen this issue otherwise and would have been none the wiser as to why some customers were having problems.
Has anyone else seen this and/or have a fix other than waiting longer? Do you know how long it takes for Apple Private Relay to update? This isn't expected behaviour of DNS?
I spoke to someone at Apple yesterday and there wasn't much they can do. I hope they're escalating internally as almost 3 days later it's still pointing users to the old IP address despite having ample time for proper DNS propagation.
Topic:
App & System Services
SubTopic:
Networking
I have been using the SCNetworkReachabilityGetFlags for 10+ years to inform users that their request won't work. In my experience this works pretty well although i am aware of the limitations.
Now, i am looking into the NWPathMonitor, and i have one situation that i'm trying to. get my head around - it's asynchronous.
Specifically, i am wondering what to do when my geofences trigger and i want to check network connectivity - i want to tell the user why the operation i'll perform because of the trigger couldn't be done.
SO. say i start a NWPathMonitor in didFinishLaunchingWithOptions. When the app is booted up because of a geofence trigger, might i not end up in a case where my didEnterRegion / didExitRegion gets called before the NWPathMonitor has gotten its first status?
The advantage here with SCNetworkReachabilityGetFlags, as i understand it, would be that it's synchronous?
If i want to upgrade to nwpathmonitor, i guess i have to do a method that creates a nwpathmonitor, uses a semaphore to wait for the first callback, then contunues?
Thoughts appreciated
Hello,
We are facing an issue with performing a DTLS handshake when our iOS application is in the background. Our app (Vocera Collaboration Suite – VCS) uses secure DTLS-encrypted communication for incoming VoIP calls.
Problem Summary:
When the app is in the background and a VoIP PushKit notification arrives, we attempt to establish a DTLS handshake over our existing socket. However, the handshake consistently fails unless the app is already in the foreground. Once the app is foregrounded, the same DTLS handshake logic succeeds immediately.
Key Questions:
Is performing a DTLS handshake while the app is in the background technically supported by iOS?
Or is this an OS-level limitation by design?
If not supported, what is the Apple-recommended alternative to establish secure DTLS communication for VoIP flows without bringing the app to the foreground?
Any guidance or clarification from Apple engineers or anyone who has solved a similar problem would be greatly appreciated.
Thank you.
Currently in our app, to identify a network switch in device we are doing NEHotspotHelper.register and then NEHotspotHelperHandler block. When the command type is evaluate and if the network.didJustJoin, we are identifying it as a network switch.
As a part of moving our code base to iOS 26, if is found that NEHotspotHelper is deprecated. What is the proper replacement for this?
Topic:
App & System Services
SubTopic:
Networking
Description:
We are investigating an issue where running a specific e-commerce iOS app inside the Xcode Simulator intermittently disrupts the Mac’s network connectivity.
When the app is launched in the Simulator, our NETransparentProxyProvider and NEFilterDataProvider extensions occasionally stop receiving traffic correctly, and shortly afterward the entire macOS DNS resolution fails. Once this happens, all apps on the Mac lose internet access until mac is restarted. Disabling extensions also fixing the issue.
This issue only appears when the app runs in the Xcode Simulator.
I would like to confirm:
Is it possible for traffic patterns or network behavior inside the Simulator to interfere with system-level Network Extension providers on macOS?
Are there known limitations or conflicts between the Simulator’s virtual networking interfaces and Network Extensions?
Any recommended debugging steps or best practices to isolate this behavior?
Any guidance, known issues, or suggestions would be appreciated.
Hello,
I am studying the Building peer-to-peer apps codebase https://developer.apple.com/documentation/wifiaware/building-peer-to-peer-apps and am wondering why no connection is ever started?
I searched the codebase and didn't find .start() be called once.
Start function I'm referencing https://developer.apple.com/documentation/network/networkconnection/start()
Are NetworkConnections started automatically?
Note that I am using QUIC NetworkConnections (NetworkConnection) in what I'm trying to do.
Is there any way to forcibly disable using QUIC? I've noticed this ends up causing issues with our ISP / router, and noticed for many of our customers as well.
Creating an ephemeral session doesn't change things, and setting the request to "assumeHttp3Capable" to false doesn't fix things either.
We are using Cloudflare Workers as the URL we are hitting, and thus aren't able to disable this server-side.
Hello,
I have an app that was using the iOS 18 Network Framework APIs. It used Peer to Peer, QUIC and Bonjour. It was all working as expected. I wanted to upgrade to the new iOS 26 Network Framework APIs (NetworkBrowser, NetworkListener, NetworkConnection...).
I have things working (multiple devices can discover each other, connection to each other and send messages to each other) but my app crashes when I go to toggle of all the networking stuff.
In the iOS 18 Network Framework API NWConnection had a .cancel() function I could use to tell the other side the connection was done.
I dont see a cancel function for NetworkConnection.
My question is - how do I properly close down a NetworkConnection and also properly tell the other side the connection is done.
I am developing a React Native app that uses UDP broadcast and device discovery over the local Wi-Fi network (similar to 4Stream).
In Debug mode everything works, but after uploading to TestFlight the local network communication stops working.
I have already added the following to Info.plist:
Hi everyone,
I am building a React Native iOS app that discovers audio devices on the local Wi-Fi network using UDP broadcast + mDNS/Bonjour lookup (similar to the “4Stream” app).
The app works 100% perfectly in Debug mode when installed directly from Xcode.
But once I upload it to TestFlight, the local-network features stop working completely:
UDP packets never arrive
Device discovery does not work
Bonjour/mDNS lookup returns nothing
Same phone, same Wi-Fi, same code → only Debug works, TestFlight fails
react-native-udp for UDP broadcast
react-native-dns-lookup for resolving hostnames
react-native-xml2js for parsing device responses