Hi,
Consider a content filter app that allows most requests. While running, it handles requests and determine what to do. It does not affect any request while it is not running.
However, during startup, it seems to block all requests, on iOS 16 or 17.
On iOS 15, the behavior is bit different. Show the picture below:
Questions
- Is this the expected behavior?
- Is this documented?
Steps to reproduce
-
Create content filter app with filter data provider with lengthy startup, something like the following:
import NetworkExtension class FilterDataProvider: NEFilterDataProvider { override func startFilter(completionHandler: @escaping ((any Error)?) -> Void) { Task { try await Task.sleep(nanoseconds: 10 * 1_000_000_000) completionHandler(nil) } } override func stopFilter(with reason: NEProviderStopReason) async {} override func handleNewFlow(_ flow: NEFilterFlow) -> NEFilterNewFlowVerdict { guard let url: String = flow.url?.absoluteString else { return .allow() } if url.contains("example.net/") { return .drop() } if url.contains("example.org/") { exit(42) } return .allow() } }
-
Install the app on a supervised iPhone or iPad.
-
Install a
WebContentFilter
profile. -
Wait for the content filter to start. You can check the status in Settings > General > VPN & Device Management > Content Filter.
-
Open Safari app.
-
Request
http://example.net/
and confirm that it is blocked. -
Request the other URLs and confirm that it is allowed.
-
Request
http://example.org
. It kills the filter data provider. -
Request some URLs quickly.
Background to the questions
We offer a content filter app that might be stopped during the device sleeps. When a non-our-app’s push notification is received, the device wakes up, and the content filter starts up. Then the push notification seems to be lost. It is observed on iOS 16 and 17, not on iOS 15.
Is this the expected behavior?
Yes and, in fact, I believe the iOS 15 behavior was in fact a bug. In security terms, iOS 15 is "failing open", which means it's possible to bypass your content filter by indirectly disturbing it's startup process (for example, but blocking or stalling specific requests).
Is this documented?
No. The current behavior is how this kind of API is expected to behave and the iOS 15 behavior was a bug.
We offer a content filter app that might be stopped during the device sleeps. When a non-our-app’s push notification is received, the device wakes up, and the content filter starts up. Then the push notification seems to be lost. It is observed on iOS 16 and 17, not on iOS 15.
If you want to reimplement the iOS 15 behavior, then you can modify your start logic to "finish" as quickly as possible and then simply allow all flows until you've finished your own initialization and can start blocking again.
__
Kevin Elliott
DTS Engineer, CoreOS/Hardware