We have a setup where the system uses proxy settings configured via a PAC file. We are investigating how NWConnection behaves inside a Network Extension (NETransparentProxyProvider) with a transparent proxy configuration based on this PAC file.
Scenario:
The browser makes a connection which the PAC file resolves as "DIRECT" (bypassing the proxy)
Our Network Extension intercepts this traffic for analysis
The extension creates a new connection using NWConnection to the original remote address.
The issue: despite the PAC file’s "DIRECT" decision, NWConnection still respects the system proxy settings and routes the connection through the proxy.
Our questions:
Is it correct that NWConnection always uses the system proxy if configured ?
Does setting preferNoProxies = true guarantee bypassing the system proxy?
Additionally:
Whitelisting IPs in the Network Extension to avoid interception is not a viable solution because IPs may correspond to multiple services, and the extension only sees IP addresses, not domains (e.g., we want to skip scanning meet.google.com traffic but still scan other Google services on the same IP range).
Are there any recommended approaches or best practices to ensure that connections initiated from a Network Extension can truly bypass the proxy (for example, for specific IP ranges or domains)?
Extensions
RSS for tagGive users access to your app's functionality and content throughout iOS and macOS using extensions.
Posts under Extensions tag
180 Posts
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
we have written a QL preview generator for some 3D data formats not supported by the AR Quicklook generators included in iOS.
however, we are struggeling with the 100 MB memory ceiling imposed on an app extension in iOS.
we have included the "Increased Memory Limit" entitlement in both the app and in the preview extensions.
nevertheless, the preview generator is limited to 100 MB, even on most recent devices like iPhone 16 Pro Max. we can even see 100 MB limit when we attach to the process with Xcode.
my question: did we miss anything? are there additional steps necessary to obtain the increased memory limit? must we explicitly apply for it? 500 MB would be fine (our preview generator does not load textures).
best regards
I have an outside Mac App Store app. It has an action extension. I can't get it to run from Xcode. I try to debug it from Safari. It shows up in the menu when I click the 'rollover' button but it doesn't show up in the UI at all. Xcode doesn't give me any indication as to what the problem is. I see this logs out in console when I try to open the action extension:
Prompting policy for hardened runtime; service: kTCCServiceAppleEvents requires entitlement com.apple.security.automation.apple-events but it is missing for accessing={TCCDProcess: identifier=BundleIdForActionExtHere, pid=6650, auid=501, euid=501, binary_path=/Applications/AppNamehere.app/Contents/PlugIns/ActionExtension.appex/Contents/MacOS/ActionExtension}, requesting={TCCDProcess: identifier=com.apple.appleeventsd, pid=550, auid=55, euid=55, binary_path=/System/Library/CoreServices/appleeventsd},
I don't see why the Action extension needs Apple events but I added it to the entitlements anyway but it doesn't seem to matter. The action extension fails to open.
Hello everyone,
I’m working on an iOS app that uses the new DeviceActivity framework to monitor and report user screen‐time in an extension (DeviceActivityReportExtension). I need to persist my processed screen‐time data into a standalone SQLite database inside the extension, but I’m running into issues opening and writing to the database file.
Here’s what I’ve tried so far:
import UIKit
import DeviceActivity
import SQLite3
class DeviceActivityReportExtension: DeviceActivityReportExtension {
private var db: OpaquePointer?
override func didReceive(_ report: DeviceActivityReport) async {
// 1. Construct path in app container:
let containerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.mycompany.myapp")
let dbURL = containerURL?.appendingPathComponent("ScreenTimeReports.db")
// 2. Open database:
if sqlite3_open(dbURL?.path, &db) != SQLITE_OK {
print("❌ Unable to open database at \(dbURL?.path ?? "unknown path")")
return
}
defer { sqlite3_close(db) }
// 3. Create table if needed:
let createSQL = """
CREATE TABLE IF NOT EXISTS reports (
id INTEGER PRIMARY KEY AUTOINCREMENT,
date TEXT,
totalScreenTime DOUBLE
);
"""
if sqlite3_exec(db, createSQL, nil, nil, nil) != SQLITE_OK {
print("❌ Could not create table: \(String(cString: sqlite3_errmsg(db)))")
return
}
// 4. Insert data:
let insertSQL = "INSERT INTO reports (date, totalScreenTime) VALUES (?, ?);"
var stmt: OpaquePointer?
if sqlite3_prepare_v2(db, insertSQL, -1, &stmt, nil) == SQLITE_OK {
sqlite3_bind_text(stmt, 1, report.date.description, -1, nil)
sqlite3_bind_double(stmt, 2, report.totalActivityDuration)
if sqlite3_step(stmt) != SQLITE_DONE {
print("❌ Insert failed: \(String(cString: sqlite3_errmsg(db)))")
}
}
sqlite3_finalize(stmt)
}
}
However:
Path issues: The extension’s sandbox is separate from the app’s. I’m not sure if I can use the same App Group container, or if there’s a better location for an on‐extension database.
Entitlements: I’ve added the App Group (group.com.mycompany.myapp) to both the main app and the extension, but the file never appears, and I still get “unable to open database” errors.
My questions are:
How do I correctly construct a file URL for an SQLite file in a DeviceActivityReportExtension?
Is SQLite the recommended approach here, or is there a more “Apple-approved” pattern for writing data from a DeviceActivity extension?
Any sample code snippets, pointers to relevant Apple documentation, or alternative approaches would be greatly appreciated!
We have a Safari extension that's been up on the App Store for about 18 months with no apparent issues. This week, however, while working on an update, we uninstalled the production version on our test machines and installed a developer version. When we had some issues, we tried to go back to the production version downloaded from the App Store, but we get an pop saying "Unable to download App." In the log, the most obviously relevant error is 'Operation not permitted'.
This occurs on several machines and different logins on those machines in both norma and safe modes. However, on another machine that never had one installed, we could still install the app from the app store, so I suspect there is something left behind that needs to be removed, but I don't know what.
FWIW, I see the download directory getting created under /Applications, but it is promptly removed when the failure popup appears.
Any suggestions?
A message filter extension is only forwarded SMSs by the OS for filtering, iMessages aren't.
But what is the situation with RCS messages? Will they be filterable by a message filtering extension?
Hello,
In our application, we have implemented an app extension to allow users to open the main app directly from the share activity window. To achieve this, we used the openURL(:) method from the NSExtensionContext class, as documented here: openURL(:).
However, we received one post from Apple stating that opening the main app directly is typically only supported in extensions such as Today widgets or iMessage apps. They also mentioned that this approach may require an additional review during the App Store submission process.
Link: https://developer.apple.com/documentation/foundation/nsextensioncontext/1416791-openurl
Could someone clarify:
If using openURL(_:) in a share extension to open the main app would lead to potential issues during App Store submission?
Are there specific guidelines or alternative approaches we should follow to ensure compliance?
Any insights or recommendations would be greatly appreciated.
Thank you!
Topic:
App & System Services
SubTopic:
General
Tags:
Mobile Core Services
Developer Tools
Extensions
When our Safari Web Extension makes a api request from its background script (registered via "scripts" in manifest.json, e.g., "background": { "scripts": ["js/background.bundle.js"] }) to our authenticated API endpoint (https://api-domain/user), the Cookie header is not included in the request. This occurs only when the extension is running within a non-default Safari User Profile. This causes our API to treat the user as unauthenticated. The exact same extension code, manifest, and API call work correctly (Cookie header is present and user is authenticated) when the extension is running in the Default Safari User Profile.
I have a simple ShareLink in my app:
let shareImage = Image(uiImage: shareUIImage)
ShareLink(item: shareImage,
subject: Text(shareText),
preview: SharePreview(shareText, image: shareImage),
label: { ImageShareButton() })
It works fine when sharing to Apple Messages and Instagram.
However it does NOT work when sharing to Telegram and Bluesky. The share sheet hesitates for a second and then closes with no action taken. Console errors include: Received port for identifier response: <(null)> with error:Error Domain=RBSServiceErrorDomain Code=1 "Client not entitled" UserInfo={RBSEntitlement=com.apple.runningboard.process-state, NSLocalizedFailureReason=Client not entitled, RBSPermanent=false})
Is this something that those third party apps need to resolve, or has anyone been able to get image sharing working with Bluesky or Telegram?
I found that on my cutomer's mac device, webflterproxyd start interferiing with the NE traffic. Tried to stop it, but "screen time" was not enabled at all.
Who started this webfilterproxyd process and how to stop it?
I have setup the extension for replaykit successfully , the bundle id and everything is correct but still the system broadcast picker view is not showing my own app to broadcast screen content when trying to do system wide broadcast.
Hi all,
In MacOS, how can I disable or enable build-in camera by program or script?
I have had content blockers in the Mac App Store for years. Ever since moving to Sonoma, doing a clean build or archive in XCode deletes the extension from Safari settings since it never gets into the built app. The only way for me to get it back is to remove the DerivedData and target, reboot, and create a target with a different name. That works and stays around in Safari settings as long as I only build and don't clean. However, a clean or an archive removes it again.
Restoring a version of the project from Time Machine that was posted to the App Store weeks or months ago doesn't work. However I can download the version of the app in the App Store, and it works, but I can't build it now from the source code that was used to build that version without going through the above process. Moving from Sonoma 14.7.1 to 14.7.2 didn't work. I would move to Sequoia if I had reason to believe that would work, but I don't.
Safari 18.2, Sonoma 14.7.2, 32GB, 2.2 GHz 6-Core Intel Core i7
使用direct distribution进行分发时,safari web extension 在safari setting 中显示没有权限读取、修改或传输任何网页的内容。
但是我在看公证日志显示插件是正常的公证的
这导致safari extension 无法使用。
公证日志
https://www.coupert.com/img/2025-04-10/notarization-log.json
I've got an iOS app with lots of extensions, some of them complex and doing a lot of stuff.
After a bug I'd like to be able to use OSLogStore to get a holistic picture of logging for the app and its extensions and send that to a debugging server to retrospectively view logs for the app and its extensions.
The constructor is OSLogStore.init(scope: OSLogStore.Scope), however scope only has one value .currentProcessIdentifier.
Implying if that is called from within the app it can only get access to logging for its process only. I tried it out to confirm this is the case - if I log something in an extension (using Logger), then run the app with code like this:
let logStore = try! OSLogStore(scope: .currentProcessIdentifier)
let oneHourAgo = logStore.position(date: Date().addingTimeInterval(-3600))
let allEntries = try! logStore.getEntries(at: oneHourAgo)
for entry in allEntries {
look at the content of the entry
Then none of the entries are from the extension.
Is there anyway from within the app I can access logging made within an extension?
My personal project is a bit further along however after not being able to get this to work in my app I fell back to a much simpler/proven implementation out there. There is this project on GitHub with a guide that implements a barebones app extension with packet tunneling. I figure this can give us common ground.
After changing the bundle and group identifiers to all end with -Caleb and or match up I tried running the app. The app extension does not work whatsoever and seemingly for reasons that are similar to my personal project.
If I pull up the console and filter for the subsystem (com.github.kean.vpn-client-caleb.vpn-tunnel) I see the following.
First you see installd installing it
0x16ba5f000 -[MIUninstaller _uninstallBundleWithIdentity:linkedToChildren:waitForDeletion:uninstallReason:temporaryReference:deleteDataContainers:wasLastReference:error:]: Destroying container com.github.kean.vpn-client-caleb.vpn-tunnel with persona 54D15361-A614-4E0D-931A-0953CDB50CE8 at /private/var/mobile/Containers/Data/PluginKitPlugin/2D0AE485-BB56-4E3E-B59E-48424CD4FD65
And then installd says this (No idea what it means)
0x16b9d3000 -[MIInstallationJournalEntry _refreshUUIDForContainer:withError:]: Data container for com.github.kean.vpn-client-caleb.vpn-tunnel is now at /private/var/mobile/Containers/Data/PluginKitPlugin/2D0AE485-BB56-4E3E-B59E-48424CD4FD65
Concerningly runningboardd seems to immediately try and stop it?
Executing termination request for: <RBSProcessPredicate <RBSProcessBundleIdentifiersPredicate| {(
"com.github.kean.vpn-client-caleb",
"com.github.kean.vpn-client-caleb.vpn-tunnel"
)}>>
[app<com.github.kean.vpn-client-caleb(54D15361-A614-4E0D-931A-0953CDB50CE8)>:1054] Terminating with context: <RBSTerminateContext| explanation:installcoordinationd app:[com.github.kean.vpn-client-caleb/54D15361-A614-4E0D-931A-0953CDB50CE8] uuid:963149FA-F712-460B-9B5C-5CE1C309B2FC isPlaceholder:Y reportType:None maxTerminationResistance:Absolute attrs:[
<RBSPreventLaunchLimitation| <RBSProcessPredicate <RBSProcessBundleIdentifiersPredicate| {(
"com.github.kean.vpn-client-caleb",
"com.github.kean.vpn-client-caleb.vpn-tunnel"
)}>> allow:(null)>
]>
Then runningboardd leaves a cryptic message
Acquiring assertion targeting system from originator [osservice<com.apple.installcoordinationd>:244] with description <RBSAssertionDescriptor| "installcoordinationd app:[com.github.kean.vpn-client-caleb/54D15361-A614-4E0D-931A-0953CDB50CE8] uuid:963149FA-F712-460B-9B5C-5CE1C309B2FC isPlaceholder:Y" ID:33-244-5222 target:system attributes:[
<RBSPreventLaunchLimitation| <RBSProcessPredicate <RBSProcessBundleIdentifiersPredicate| {(
"com.github.kean.vpn-client-caleb",
"com.github.kean.vpn-client-caleb.vpn-tunnel"
)}>> allow:(null)>
]>
And that seems to be all I have to go off of.... If I widen my search a bit I can see backboardd saying things like
Connection removed: IOHIDEventSystemConnection uuid:57E97E5D-8CDE-467B-81CA-36A93C7684AD pid:1054 process:vpn-client type:Passive entitlements:0x0 caller:BackBoardServices: <redacted> + 280 attributes:{
HighFrequency = 1;
bundleID = "com.github.kean.vpn-client-caleb";
pid = 1054;
} state:0x1 events:119 mask:0x800 dropped:0 dropStatus:0 droppedMask:0x0 lastDroppedTime:NONE
Or
Removing client connection <BKHIDClientConnection: 0xbf9828cd0; IOHIDEventSystemConnectionRef: 0xbf96d9600; vpid: 1054(vAF7); taskPort: 0x5D777; bundleID: com.github.kean.vpn-client-caleb> for client: IOHIDEventSystemConnection uuid:57E97E5D-8CDE-467B-81CA-36A93C7684AD pid:1054 process:vpn-client type:Passive entitlements:0x0 caller:BackBoardServices: <redacted> + 280 attributes:{
HighFrequency = 1;
bundleID = "com.github.kean.vpn-client-caleb";
pid = 1054;
} state:0x1 events:119 mask:0x800 dropped:0 dropStatus:0 droppedMask:0x0 lastDroppedTime:NONE source:HID
There's really nothing in the sysdiagnose either. No crash no nothing.
I am stumped. Any idea what might be going wrong for me here? Has something about the way app extensions or sandbox rules work changed in later OSes?
I'm building a macOS Google Chrome extension.
I need to be able to send messages from the Chrome extension to the macOS app
What's the set up flow?
I've heard about native messaging, but I struggle to implement it.
I've heard about XPC, but not sure JS can send messages to a macOS XPC service.
My CoreSpotlight extension seems to exceed the 6 MB memory limit. What’s the best way to debug this?
I've tried to attach the debugger on the Simulator but the extension seems to be never launched when I trigger the reindex from Developer settings. Is this supposed to work?
On device, I am able to attach the debugger. However, I can neither transfer the debug session to Instruments, nor display the memory graph. So I've no idea how the memory is used.
Any recommendations how to move forward? Is there a way to temporarily disable the memory limit since even with LLDB attached, the extension is killed.
I’m having an issue with my Credential Provider Extension for passkey registration. On the browser I click on registration, in IOS i can select my App for passkey registration with a continue button. Wenn I click the continue button the prepareInterface(forPasskeyRegistration:) function is called but the MainInterface is not shown —it only appears when I click the continue button a second time.
Here’s a simplified version of my prepareInterface method:
override func prepareInterface(forPasskeyRegistration registrationRequest: ASCredentialRequest) {
guard let request = registrationRequest as? ASPasskeyCredentialRequest,
let identity = request.credentialIdentity as? ASPasskeyCredentialIdentity else {
extensionContext.cancelRequest(withError: ASExtensionError(.failed))
return
}
self.identity = identity
self.request = request
log.info("prepareInterface called successfully")
}
In viewDidAppear, I trigger FaceID authentication and complete the registration process if register is true. However, the UI only shows after a second “Continue” tap.
Has anyone encountered this behavior or have suggestions on how to ensure the UI appears immediately after prepareInterface is called? Could it be a timing or lifecycle issue with the extension context?
Thanks for any insights!
Safari Version 14.0.1 (16610.2.11.51.8)
I am porting a Chrome/Firefox/Edge extension to Safari Web Extension. Mostly, the process was painless, I am, however, seeing quite different behavior in the tab ids generated by Safari compared to Chrome, Firefox, and Edge. My extension has callbacks for each of these browser.webNavigation events:
browser.webNavigation.onBeforeNavigate
browser.webNavigation.onCommitted
browser.webNavigation.onDOMContentLoaded
In each of these I rely on the tab id for various future tab targeting operations. When opening a new tab, the details object passed to each of these callbacks has a non-zero tabId on Chrome, Firefox, and Edge. However, in Safari, the tabId is always zero. To debug, I added one more callback:
browser.webNavigation.onCompleted
At this point Safari finally has a non-zero tabId in the details param. Needless to say this is causing some consternation with achieving the same outcomes as tab tracking on Chrome, Firefox, and Edge. It's like Safari is treating new tabs as "non tabs" until navigation completes. You can even see it when trying to get the tab by tabId=0:
browser.tabs.get(tabId) // tabId=0 here
	.then(tab => {
		// tab is undefined
	});
Seems like this might be a bug. I can't imagine why the behavior is so different from other browsers. Any ideas on how to work around?